diff options
Diffstat (limited to 'lib/wx/api_gen')
27 files changed, 9484 insertions, 0 deletions
diff --git a/lib/wx/api_gen/Makefile b/lib/wx/api_gen/Makefile new file mode 100644 index 0000000000..c6b65b60bc --- /dev/null +++ b/lib/wx/api_gen/Makefile @@ -0,0 +1,74 @@ +# +# %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% +# +ERLC = erlc +ERL = erl +EBIN = . + +# make WXGTK_DIR=/wxWidgets-2.8.5/include +WXGTK_DIR = /usr/include/wx-2.8 +#WXGTK_DIR = /opt/wxgtk2.8.9/include/wx-2.8 +GL_DIR = /usr/include/GL + +ERL_COMPILE_FLAGS=+debug_info +warn_unused_vars + +COMPILER = gen_util wx_gen wx_gen_erl wx_gen_cpp +COMPILER_T = $(COMPILER:%=$(EBIN)/%.beam) + +GL_COMP = gl_gen gl_gen_erl gl_gen_c +GL_COMP_T = $(GL_COMP:%=$(EBIN)/%.beam) + +TARGET_EDIR = ../src/gen +TARGET_CDIR = ../c_src/gen + +C_TARGETS = wxe_funcs.cpp +GL_C_TARGETS = gl_funcs.cpp + +WX = $(TARGET_CDIR)/$(C_TARGETS) + +GL = $(TARGET_CDIR)/$(GL_C_TARGETS) + +opt: $(WX) $(GL) + +$(WX): wxxml_generated $(COMPILER_T) wxapi.conf $(wildcard wx_extra/wx*.c_src) $(wildcard wx_extra/wx*.erl) + erl -noshell -run wx_gen code + +wxxml_generated: wx_doxygen.conf wx_extra/bugs.h wx_extra/wxe_evth.h + sed -e 's|@WXGTK_DIR@|$(WXGTK_DIR)|g' wx_doxygen.conf > wx_doxygen + doxygen wx_doxygen && touch wxxml_generated + +glxml_generated: gl_doxygen.conf + sed -e 's|@GL_DIR@|$(GL_DIR)|g' gl_doxygen.conf > gl_doxygen + doxygen gl_doxygen && touch glxml_generated + + +$(GL): glxml_generated $(GL_COMP_T) glapi.conf + erl -noshell -run gl_gen code + +%.beam: %.erl wx_gen.hrl gl_gen.hrl + $(ERLC) -W $(ERL_FLAGS) $(ERL_COMPILE_FLAGS) $< -o$(EBIN) + +# TODO split cleans into separate targets? +complete_clean: + rm -f gl_doxygen wx_doxygen wx_xml/*.x* gl_xml/*.x* + rm -f glxml_generated wxxml_generated + $(MAKE) clean +clean: + rm -f *~ + rm -f $(COMPILER_T) $(GL_COMP_T) + rm -f wx_extra/*~ diff --git a/lib/wx/api_gen/README b/lib/wx/api_gen/README new file mode 100644 index 0000000000..3c49f7b2a5 --- /dev/null +++ b/lib/wx/api_gen/README @@ -0,0 +1,26 @@ +API GENERATION: + Most of the code in wx is generated. + Users of wxErlang should not normally need to regenerate the generated code, + as it is checked in by wxErlang developers, when changes are made. + 2008-09-29 Code checked in is currently generated from wxwidgets 2.8.7. + +REQUIREMENTS: + The code generation requires doxygen (1.4.6) which is + used to parse wxWidgets c++ headers and generate xml files (in + wx_xml/). + + (2008-09-29 doxygen 1.4.6 is required. + Later versions of Doxygen - up to 1.5.6 at least - have a bug in the xml generation + which causes us problems. This has been logged and we are waiting for a fix.) + +CONFIGURATION: + wxapi.conf contains the specification to the code generator. The code + generator reads the specification and parses the xml files and + produces the erlang and the 'C' code. + + Adding/changing stuff/classes should be done by updating wxapi.conf + and running make. Sometimes the code generator will require changes, + I havn't thought of everything yet. + +CONTRIBUTION: + Send me patches or update the svn version. diff --git a/lib/wx/api_gen/gen_util.erl b/lib/wx/api_gen/gen_util.erl new file mode 100644 index 0000000000..d47fd579a5 --- /dev/null +++ b/lib/wx/api_gen/gen_util.erl @@ -0,0 +1,246 @@ +%% +%% %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% +%% +%% Some utilities + +-module(gen_util). +-compile(export_all). + +lowercase([F|R]) when F >= $A, F =< $Z -> [F+($a-$A)|R]; +lowercase(Str) when is_list(Str) -> Str. + +lowercase_all([F|R]) when F >= $A, F =< $Z -> [F+($a-$A)|lowercase_all(R)]; +lowercase_all([F|R]) -> [F|lowercase_all(R)]; +lowercase_all([]) -> []. + +uppercase([F|R]) when F >= $a, F =< $z -> [F+($A-$a)|R]; +uppercase(Str) when is_list(Str) -> Str. + +uppercase_all([F|R]) when F >= $a, F =< $z -> [F+($A-$a)|uppercase_all(R)]; +uppercase_all([A|R]) -> [A|uppercase_all(R)]; +uppercase_all([]) -> []. + + +strip_name([H|R1],[H|R2]) -> + strip_name(R1,R2); +strip_name(String,[]) -> String. + +open_write(File) -> + %% io:format("Generating ~s~n",[File]), + {ok, Fd} = file:open(File++".temp", [write]), + put(current_file, {Fd,File}). + + +close() -> + case get(current_file) of + undefined -> + ok; + {closed, File} -> + io:format("Closing twice ~s~n",[File]); + {Fd,File} -> + file:close(Fd), + case os:cmd("diff " ++ File ++ " " ++ File ++ ".temp" ++ "| head -30") of + [] -> + ok = file:delete(File ++ ".temp"), + %% So that make understands that we have made this + case os:getenv("CLEARCASE_ROOT") of + false -> os:cmd("touch " ++ File); + _ -> ignore + end, + ok; + Diff -> + case check_diff(Diff) of + copyright -> %% We ignore copyright changes only + ok = file:delete(File ++ ".temp"); + _ -> + io:format("Diff in ~s~n~s ~n", [File, Diff]), + case file:rename(File ++ ".temp", File) of + ok -> ok; + _ -> + io:format("***** Failed to save file ~p ~n",[File]) + end + end + end, + put(current_file, {closed, File}) + end. + + +check_diff(Diff) -> + try + [_,D1,_,D2|Tail] = re:split(Diff, "\n"), + case Tail of + [] -> ok; + [<<>>] -> ok; + _ -> throw(diff) + end, + <<_, _, "%% Copyright", _/binary>> = D1, + <<_, _, "%% Copyright", _/binary>> = D2, + copyright + catch + throw:_ -> diff; + error:{badmatch,_} -> + diff; + _:What -> + io:format("~p:~p: ~p ~p~n", [?MODULE,?LINE, What, erlang:get_stacktrace()]), + diff + end. + +w(Str) -> + w(Str, []). +w(Str,Args) -> + {Fd,_} = get(current_file), + io:format(Fd, Str, Args). + +args(Fun, Limit, List) -> + args(Fun, Limit, List, infinity, 0). + +args(Fun, Limit, List, Max) -> + args(Fun, Limit, List, Max, 0). + +args(_Fun, _Limit, [], _Max, _) -> ""; %% No args +args(Fun, _Limit, [Last], _Max, _Pos) -> + case Fun(Last) of + skip -> ""; %% FIXME bug if last skips + Str -> Str + end; +args(Fun, Limit, [H|R], Max, Pos) -> + case Fun(H) of + skip -> args(Fun,Limit,R, Max, Pos); + Str -> + {NL, NewPos} = + case length(Str) + Pos of + Curr when Curr > Max -> + {"\n ", 0}; + Curr -> + {"", Curr} + end, + case args(Fun,Limit,R, Max, NewPos) of + "" -> Str; + End -> Str ++ Limit ++ NL ++ End + end + end. + + + + +tokens(S) -> + tokens1(S, " \t\r\n(){}*;,@", []). +tokens(S,Seps) -> + tokens1(S, Seps, []). + +tokens1([C|S], Seps, Toks) -> + case lists:member(C, Seps) of + true -> tokens1(S, Seps, [C|Toks]); + false -> tokens2(S, Seps, Toks, [C]) + end; +tokens1([], _Seps, Toks) -> + replace_and_remove(Toks, []). + +tokens2([C|S], Seps, Toks, Cs) -> + case lists:member(C, Seps) of + true -> tokens1(S, Seps, [C, lists:reverse(Cs) |Toks]); + false -> tokens2(S, Seps, Toks, [C|Cs]) + end; +tokens2([], _Seps, Toks, Cs) -> + replace_and_remove([lists:reverse(Cs)|Toks], []). + +replace_and_remove([E|R], Acc) when is_list(E) -> %% Keep everything that is a word + replace_and_remove(R, [E|Acc]); +replace_and_remove([$\n | R], Acc) -> %% It is semi line oriented so keep eol + replace_and_remove(R, [eol|Acc]); +replace_and_remove([$( | R], Acc) -> + replace_and_remove(R, ["("|Acc]); +replace_and_remove([$) | R], Acc) -> + replace_and_remove(R, [")"|Acc]); +replace_and_remove([${ | R], Acc) -> + replace_and_remove(R, ["{"|Acc]); +replace_and_remove([$} | R], Acc) -> + replace_and_remove(R, ["}"|Acc]); +replace_and_remove([$| | R], Acc) -> + replace_and_remove(R, ["|"|Acc]); +replace_and_remove([$* | R], Acc) -> + replace_and_remove(R, ["*"|Acc]); +replace_and_remove([$& | R], Acc) -> + replace_and_remove(R, [$&|Acc]); +replace_and_remove([$<,$< | R], Acc) -> + replace_and_remove(R, ["<<"|Acc]); +replace_and_remove([$, | R], Acc) -> + replace_and_remove(R, [cont|Acc]); +replace_and_remove([$; | R], Acc) -> + replace_and_remove(R, [eoe|Acc]); +replace_and_remove([$@ | R], Acc) -> + replace_and_remove(R, [directive|Acc]); + +replace_and_remove([_E|R], Acc) -> %% Ignore everthing else + replace_and_remove(R, Acc); +replace_and_remove([], Acc) -> + Acc. + +halt(Reason) -> + case process_info(group_leader(), status) of + {_,waiting} -> + %% Now all output data is down in the driver. + %% Give the driver some extra time before halting. + receive after 10 -> ok end, + erlang:halt(Reason); + _ -> + %% Probably still processing I/O requests. + receive after 20 -> ok end, + gen_util:halt(Reason) + end. + +erl_copyright() -> + w("%%~n",[]), + w("%% %CopyrightBegin%~n",[]), + w("%% ~n",[]), + w("%% Copyright Ericsson AB 2008-2009. All Rights Reserved.~n",[]), + w("%% ~n",[]), + w("%% The contents of this file are subject to the Erlang Public License,~n",[]), + w("%% Version 1.1, (the \"License\"); you may not use this file except in~n",[]), + w("%% compliance with the License. You should have received a copy of the~n",[]), + w("%% Erlang Public License along with this software. If not, it can be~n",[]), + w("%% retrieved online at http://www.erlang.org/.~n",[]), + w("%% ~n",[]), + w("%% Software distributed under the License is distributed on an \"AS IS\"~n",[]), + w("%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See~n",[]), + w("%% the License for the specific language governing rights and limitations~n",[]), + w("%% under the License.~n",[]), + w("%% ~n",[]), + w("%% %CopyrightEnd%~n",[]). + +c_copyright() -> + w("/*~n",[]), + w(" * %CopyrightBegin%~n",[]), + w(" * ~n",[]), + w(" * Copyright Ericsson AB 2008-2009. All Rights Reserved.~n",[]), + w(" * ~n",[]), + w(" * The contents of this file are subject to the Erlang Public License,~n",[]), + w(" * Version 1.1, (the \"License\"); you may not use this file except in~n",[]), + w(" * compliance with the License. You should have received a copy of the~n",[]), + w(" * Erlang Public License along with this software. If not, it can be~n",[]), + w(" * retrieved online at http://www.erlang.org/.~n",[]), + w(" * ~n",[]), + w(" * Software distributed under the License is distributed on an \"AS IS\"~n",[]), + w(" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See~n",[]), + w(" * the License for the specific language governing rights and limitations~n",[]), + w(" * under the License.~n",[]), + w(" * ~n",[]), + w(" * %CopyrightEnd% ~n",[]), + w("*/~n",[]). + + diff --git a/lib/wx/api_gen/gl_doxygen.conf b/lib/wx/api_gen/gl_doxygen.conf new file mode 100644 index 0000000000..e29a3654b5 --- /dev/null +++ b/lib/wx/api_gen/gl_doxygen.conf @@ -0,0 +1,228 @@ +# Doxyfile 1.4.3 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = wxe +PROJECT_NUMBER = 0.1 +OUTPUT_DIRECTORY = ./ +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = YES +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = YES +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = NO +INLINE_INFO = NO +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = NO +GENERATE_TESTLIST = NO +GENERATE_BUGLIST = NO +GENERATE_DEPRECATEDLIST= NO +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = NO +WARN_IF_UNDOCUMENTED = NO +WARN_IF_DOC_ERROR = NO +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = @GL_DIR@/gl.h @GL_DIR@/glext.h @GL_DIR@/glu.h +#INPUT = /usr/include/GL/gl.h /usr/include/GL/glext.h /usr/include/GL/glu.h +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +USE_HTAGS = NO +VERBATIM_HEADERS = NO +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = NO +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = YES +XML_OUTPUT = ./gl_xml/ +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = NO +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = \ + APIENTRY="" \ + WINGDIAPI="" \ + GLAPI="" \ + GL_GLEXT_PROTOTYPES="1" + +EXPAND_AS_DEFINED = YES +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = NO +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO + diff --git a/lib/wx/api_gen/gl_gen.erl b/lib/wx/api_gen/gl_gen.erl new file mode 100644 index 0000000000..91a6a1adbf --- /dev/null +++ b/lib/wx/api_gen/gl_gen.erl @@ -0,0 +1,687 @@ +%% +%% %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 : gl_gen.erl +%%% Author : Dan Gudmundsson <[email protected]> +%%% Description : +%%% +%%% Created : 16 Apr 2007 by Dan Gudmundsson <[email protected]> +%%%------------------------------------------------------------------- +-module(gl_gen). + +-export([code/0]). + +-include_lib("xmerl/include/xmerl.hrl"). +-include("gl_gen.hrl"). + +-import(lists, [foldl/3,foldr/3,reverse/1,reverse/2,keysearch/3,map/2,filter/2]). +-import(proplists, [get_value/2,get_value/3]). + +-import(gen_util,[uppercase_all/1]). + +-compile(export_all). + +code() -> safe(fun gen_code/0,true). + +devcode() -> spawn(fun() -> safe(fun gen_code/0,false) end). + +safe(What, QuitOnErr) -> + try + What(), + io:format("Completed succesfully~n~n", []), + QuitOnErr andalso gen_util:halt(0) + catch Err:Reason -> + catch gen_util:close(), + io:format("Error ~p: ~p:~p~n ~p~n", + [get(current_func),Err,Reason,erlang:get_stacktrace()]), + timer:sleep(1999), + QuitOnErr andalso gen_util:halt(1) + end. + +gen_code() -> + {ok, Opts0} = file:consult("glapi.conf"), + erase(func_id), + Opts = init_defs(Opts0), + GLUDefs = parse_glu_defs(Opts), + GLDefs = parse_gl_defs(Opts), + {GLUDefines,GLUFuncs} = setup(GLUDefs, Opts), + {GLDefines,GLFuncs} = setup(GLDefs, Opts), + gl_gen_erl:glu_defines(GLUDefines), + gl_gen_erl:glu_api(GLUFuncs), + + gl_gen_erl:gl_defines(GLDefines), + gl_gen_erl:gl_api(GLFuncs), + gl_gen_erl:gen_debug(GLFuncs,GLUFuncs), + gl_gen_c:gen(GLFuncs,GLUFuncs), + ok. + +init_defs(Opts0) -> + Opts0. + +parse_glu_defs(Opts0) -> + All = foldl(fun(File, Acc) -> load_file(File,Opts0,Acc) end, [], ["glu"]), + reverse(All). + +parse_gl_defs(Opts0) -> + All = foldl(fun(File, Acc) -> load_file(File,Opts0,Acc) end, [], ["gl","glext"]), + reverse(All). + +load_file(FileName, Opts, Acc) -> + File = filename:join(["gl_xml",FileName ++ "_8h.xml"]), + put({loaded, FileName}, true), + case xmerl_scan:file(File, [{space, normalize}]) of + {error, enoent} -> + io:format("Skipped File not found ~p ~n", [File]), + Acc; + {Doc, _} -> + io:format("Scanning ~p ~n", [File]), + %% It's duplicated in xml get sectiondef only once. + Content = find_data(Doc#xmlElement.content), + lists:foreach(fun(D) -> extract_argnames(D) end, Content), + foldl(fun(Data,Acc0) -> parse_file(Data, Opts, Acc0) end, + Acc, Content) + end. + +extract_argnames(#xmlElement{name=memberdef,attributes=Attr,content=C}) -> + case keysearch(kind, #xmlAttribute.name, Attr) of + {value, #xmlAttribute{value = "typedef"}} -> + parse_typedef(C,undefined); + _ -> + ok + end; +extract_argnames(_) -> ok. + +parse_typedef([#xmlElement{name=argsstring,content=[#xmlText{value=AS}]}|R],_) -> + parse_typedef(R,AS); +parse_typedef([#xmlElement{name=name}|_],undefined) -> + skip; +parse_typedef([#xmlElement{name=name,content=[#xmlText{value=N}]}|_],AS) -> + Args0 = string:tokens(AS," ,()*[]"), + try + Args = get_arg_names(Args0), + put({typedef,string:strip(N)},Args) + catch _:Where -> + io:format("Error ~p: ~p ~p~n", [N,Args0,Where]), + ?error(arg_names) + end; +parse_typedef([_|R],AS) -> + parse_typedef(R,AS); +parse_typedef([],_) -> skip. + +get_arg_names(As0) -> + Args = lists:filter(fun("const") -> false; (_) -> true end, As0), + get_arg_names(Args, []). + +get_arg_names([_Type,Name|R],Acc) -> + get_arg_names(R, [Name|Acc]); +get_arg_names([],Acc) -> reverse(Acc); +get_arg_names(["void"],[]) -> []; +get_arg_names(Error,_Acc) -> exit(Error). + +%% Avoid bugs in (old) doxygen..the new one doesn't have 'em +find_data([#xmlElement{name=compounddef, content=C}|_]) -> find_data(C); +find_data([#xmlElement{name=sectiondef, attributes=Attr, content=C}|R]) -> + case keysearch(kind, #xmlAttribute.name, Attr) of + {value, _} -> %% The new one have func define typedef + find_data(R) ++ C; + false -> + C + end; +find_data([_Hmm|R]) -> +%% case _Hmm of +%% #xmlElement{} -> +%% io:format("0 ~p ~n",[_Hmm#xmlElement.name]); +%% _ -> +%% ok +%% end, + find_data(R); +find_data([]) -> []. + +parse_file(#xmlElement{name=memberdef,attributes=Attr, content=C}, Opts, Acc) -> + case keysearch(kind, #xmlAttribute.name, Attr) of + {value, #xmlAttribute{value = "function"}} -> + try + Def = parse_func(C, Opts), + [Def|Acc] + catch throw:skip -> Acc + after erase(current_func) + end; + {value, #xmlAttribute{value = "define"}} -> + try + Def = parse_define(C, #def{}, Opts), + [Def|Acc] + catch throw:skip -> Acc + end; + {value, #xmlAttribute{value = "typedef"}} -> + Acc; + _W -> + io:format("Hmm ~p~n",[_W]), + Acc + end; +parse_file(_Hmm,_,Acc) -> + Acc. + +parse_define([#xmlElement{name=name,content=[#xmlText{value="API" ++ _}]}|_],_Def,_Os) -> + throw(skip); +parse_define([#xmlElement{name=name,content=[#xmlText{value="GLAPI"++_}]}|_],_Def,_Os) -> + throw(skip); +parse_define([#xmlElement{name=name,content=[#xmlText{value="WINGDIAPI"++_}]}|_],_Def,_Os) -> + throw(skip); +parse_define([#xmlElement{name=name,content=[#xmlText{value=Name}]}|R], Def, Os) -> + parse_define(R, Def#def{name=Name}, Os); +parse_define([#xmlElement{name=initializer,content=[#xmlText{value=V}]}|_],Def,_Os) -> + Val0 = string:strip(V), + try + case Val0 of + "0x" ++ Val1 -> + Val = http_util:hexlist_to_integer(Val1), + Def#def{val=Val, type=hex}; + _ -> + Val = list_to_integer(Val0), + Def#def{val=Val, type=int} + end + catch _:_ -> + Def#def{val=Val0, type=string} + end; +parse_define([_|R], D, Opts) -> + parse_define(R, D, Opts); +parse_define([], D, _Opts) -> + D. + +parse_func(Xml, Opts) -> + {Func,_} = foldl(fun(X,Acc) -> parse_func(X,Acc,Opts) end, {#func{},1}, Xml), + #func{params=Args0,type=Type0} = Func, + Args = filter(fun(#arg{type=void}) -> false; (_) -> true end, Args0), + #arg{type=Type} = + patch_param(Func#func.name,#arg{name="result",type=Type0},Opts), + Func#func{params=reverse(Args), type=Type}. + +parse_func(#xmlElement{name=type, content=C}, {F,AC}, Os) -> + Type = parse_type(drop_empty(C), Os), + {F#func{type=Type},AC}; +parse_func(#xmlElement{name=name, content=[#xmlText{value=C}]},{F,AC},Os) -> + Func = string:strip(C), + put(current_func, Func), + {F#func{name=name(Func,Os)},AC}; +parse_func(#xmlElement{name=param, content=C},{F,AC},Os) -> + Parse = fun(Con, Ac) -> parse_param(Con, Ac, Os) end, + Param0 = foldl(Parse, #arg{}, drop_empty(C)), + Param = fix_param_name(Param0, F, AC), + {add_param(Param, Os, F),AC+1}; +parse_func(_, F,_) -> + F. + +fix_param_name(A=#arg{name=undefined,type=T},#func{name=Func},Count) -> + TDName = "PFN" ++ uppercase_all(Func) ++ "PROC", + case get({typedef,TDName}) of + undefined when T == void -> + A; + undefined -> + io:format("Didn't find typedef for: ~s~n", [TDName]), + exit(aargh); + AS -> + try A#arg{name = lists:nth(Count, AS)} + catch _:_ -> A + end + end; +fix_param_name(A,_,_) -> A. + +parse_param(#xmlElement{name=type,content=C}, Arg, Os) -> + Arg#arg{type=parse_type(drop_empty(C),Os)}; +parse_param(#xmlElement{name=declname,content=[C]},Arg,_Os) -> + #xmlText{value=Name} = C, + Arg#arg{name=Name}; +parse_param(#xmlElement{name=array,content=[#xmlText{value=C}]}, + Arg=#arg{type=Type0},_Os) -> + try + [Int] = string:tokens(C, "[] "), + Val = list_to_integer(Int), + Arg#arg{type=Type0#type{single={tuple,Val}, by_val=true}} + catch _:_ -> + ?warning("Undefined Array size ~p in ~p ~p~n", + [Arg, get(current_func), C]), + Arg#arg{type=Type0#type{single={tuple,undefined}, by_val=true}} + end; + +%% Skip these +parse_param(#xmlElement{name=definition}, Arg, _) -> Arg; +parse_param(#xmlElement{name=argsstring}, Arg,_) -> Arg; +parse_param(#xmlElement{name=briefdescription}, Arg,_) -> Arg; +parse_param(#xmlElement{name=detaileddescription}, Arg,_) -> Arg; +parse_param(#xmlElement{name=inbodydescription}, Arg,_) -> Arg; +parse_param(#xmlElement{name=location}, Arg,_) -> Arg; +parse_param(Other, Arg,_) -> + io:format("Unhandled Param ~p ~n in ~p~n", [Other,Arg]), + ?error(unhandled_param). + +add_param(Arg0=#arg{type=T0}, Opts, F=#func{name=Name,params=Args}) -> + Arg = case T0 of +%% #type{mod=[const],ref={pointer,1},name="GLubyte"} -> +%% Arg0#arg{type=T0#type{base=binary}}; + #type{mod=[const]} -> Arg0; %% In is true default + #type{ref={pointer,_}} -> Arg0#arg{in=false, + type=T0#type{single=undefined}}; + _ -> Arg0 + end, + Patched = patch_param(Name,Arg,Opts), + F#func{params=[Patched|Args]}. + +patch_param(Method,P = #arg{name=ArgName},AllOpts) -> + %%io:format("~p ~n", [Method]), + case lookup(Method,AllOpts,undefined) of + undefined -> P; + What -> + %% io:format("~p ~p => ~p~n", [Method, ArgName, What]), + case What of + {ArgName,Fopt} when is_list(Fopt) -> + foldl(fun handle_arg_opt/2,P,Fopt); + {ArgName,Fopt} -> + handle_arg_opt(Fopt,P); + {_,_} -> P; + Opts when is_list(Opts) -> + case get_value(ArgName, Opts, undefined) of + undefined -> P; + List when is_list(List) -> + foldl(fun handle_arg_opt/2,P,List); + Val -> + handle_arg_opt(Val,P) + end + end + end. + +handle_arg_opt(skip, P) -> P#arg{where=c}; +%%handle_arg_opt(nowhere, P) -> P#arg{where=nowhere}; +%%handle_arg_opt(skip_member, _P) -> throw(skip_member); +handle_arg_opt(in, P) -> P#arg{in=true}; +handle_arg_opt(out, P) -> P#arg{in=false}; +handle_arg_opt(both, P) -> P#arg{in=both}; +handle_arg_opt(binary, P=#arg{type=T}) -> + P#arg{type=T#type{size=undefined,base=binary}}; +handle_arg_opt({binary,Sz}, P=#arg{type=T}) -> + P#arg{type=T#type{size=Sz,base=binary}}; +handle_arg_opt({type,Type}, P=#arg{type=T}) -> P#arg{type=T#type{name=Type}}; +handle_arg_opt({single,Opt},P=#arg{type=T}) -> P#arg{type=T#type{single=Opt}}; +handle_arg_opt({base,Opt}, P=#arg{type=T}) -> P#arg{type=T#type{base=Opt}}; +handle_arg_opt({c_only,Opt},P) -> P#arg{where=c, alt=Opt}. + +parse_type([], _Os) -> void; +parse_type(C, Os) -> + {Type,_Info} = foldl(fun extract_type_info/2,{[],undefined},C), + Empty = #type{}, + case parse_type2(reverse(Type),Empty,Os) of + Empty -> ?error({strange_type, Type}); + Assert -> Assert + end. + +extract_type_info(#xmlText{value=Value}, {Acc, Info}) -> + {reverse(foldl(fun extract_type_info2/2, [], + string:tokens(Value, " "))) ++ Acc, Info}; +extract_type_info(#xmlElement{name=ref,attributes=As, + content=[#xmlText{value=V}]}, + {Acc,undefined}) -> + {value, #xmlAttribute{value = Refid}} = + keysearch(refid,#xmlAttribute.name,As), + {value, #xmlAttribute{value = Kind}} = + keysearch(kindref,#xmlAttribute.name,As), + {reverse(foldl(fun extract_type_info2/2, [], + string:tokens(V, " "))) ++ Acc, + {Kind,Refid}}; +extract_type_info(What,Acc) -> + ?error({parse_error,What,Acc}). + +extract_type_info2("const",Acc) -> [const|Acc]; +extract_type_info2("*", [{by_ref,{pointer,N}}|Acc]) -> + [{by_ref,{pointer,N+1}}|Acc]; +extract_type_info2("*", Acc) -> [{by_ref,{pointer,1}}|Acc]; +extract_type_info2("**", Acc) -> [{by_ref,{pointer,2}}|Acc]; +extract_type_info2(Type, Acc) -> [Type|Acc]. + +parse_type2(["void"], _T, _Opts) -> void; +parse_type2([N="void"|R], T, Opts) -> + parse_type2(R,T#type{name=N},Opts); +parse_type2([const|R],T=#type{mod=Mod},Opts) -> + parse_type2(R,T#type{mod=[const|Mod]},Opts); +parse_type2(["unsigned"|R],T=#type{mod=Mod},Opts) -> + parse_type2(R,T#type{mod=[unsigned|Mod]},Opts); +parse_type2([N="GLenum"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=4, base=int},Opts); +parse_type2([N="GLboolean"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=1, base=bool},Opts); +parse_type2([N="GLbitfield"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=4, base=int},Opts); +parse_type2([N="GLvoid"|R],T,Opts) -> + parse_type2(R,T#type{name=N, base=idx_binary},Opts); + +parse_type2([N="GLbyte"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=1, base=int},Opts); +parse_type2([N="GLubyte"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=1, base=int},Opts); +parse_type2([N="GLshort"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=2, base=int},Opts); +parse_type2([N="GLushort"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=2, base=int},Opts); +parse_type2([N="GLint"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=4, base=int},Opts); +parse_type2([N="GLuint"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=4, base=int},Opts); +parse_type2([N="GLsizei"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=4, base=int},Opts); + +parse_type2([N="GLfloat"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=4,base=float},Opts); +parse_type2([N="GLdouble"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=8,base=float},Opts); +parse_type2([N="GLclampf"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=4,base=float},Opts); +parse_type2([N="GLclampd"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=8,base=float},Opts); +parse_type2([N="GLhandleARB"|R],T,Opts) -> + parse_type2(R,T#type{name=N, size=8,base=int},Opts); +parse_type2(["GLchar" ++ _ARB|R],T,Opts) -> + parse_type2(R,T#type{name="GLchar",size=1,base=string},Opts); +parse_type2(["GLUquadric"|R],T,Opts) -> + parse_type2(R,T#type{name="GLUquadric",size=8,base=int},Opts); +parse_type2(["GLintptr" ++ _ARB|R],T,Opts) -> + parse_type2(R,T#type{name="GLintptr",size=8,base=int},Opts); +parse_type2(["GLsizeiptr" ++ _ARB|R],T,Opts) -> + parse_type2(R,T#type{name="GLsizeiptr",size=8,base=int},Opts); + +parse_type2([{by_ref,Ref}|R],T,Opts) -> + parse_type2(R,T#type{ref=Ref,by_val=false},Opts); + +%% Let type errors be seen later because we don't know if these unhandled types +%% will be used. +parse_type2(_A = [Name|R],T,Opts) -> +%% io:format("unhandled ~p ~p ~n",[_A,T]), + New = T#type{name={unhandled,Name,get(current_func)}}, + parse_type2(R,New,Opts); +parse_type2([], T, _) -> T. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Function mangling %% + +setup(Defs,Opts) -> + {Fs0,Ds0} = + foldr(fun(F=#func{name=N},{Fs,Ds}) -> + case put(N,F) of + undefined -> + {[N|Fs],Ds}; + _ -> %% Duplicate + {Fs,Ds} + end; + (D=#def{}, {Fs,Ds}) -> + {Fs,[D|Ds]} + end, {[],[]}, Defs), + Fs = setup_functions(Fs0,Opts,[]), + erase(current_func), + %% Remove duplicates but keep order + {Ds,_} = foldl(fun(D=#def{name=Name},{Keep,Defined}) -> + case gb_sets:is_member(Name,Defined) of + true -> {Keep,Defined}; + false -> {[D|Keep],gb_sets:add(Name,Defined)} + end + end, {[],gb_sets:empty()}, Ds0), + {reverse(Ds),Fs}. + +setup_functions([F0|Defs],Opts,Acc) -> + put(current_func, F0), + {Name, Ext} = get_extension(F0,Opts), + %%io:format("~p = ~p + ~p~n", [F0, Name, Ext]), + Skip = (not keep(F0,Opts)) andalso (skip(F0,Opts) orelse skip(Ext,Opts)), + case Skip of + true -> + setup_functions(Defs,Opts,Acc); + false -> + case setup_extension(Name,Ext,Opts) of + skip -> + setup_functions(Defs,Opts,Acc); + New -> + setup_functions(Defs,Opts,[New|Acc]) + end + end; +setup_functions([],_, Acc) -> reverse(Acc). + +setup_extension(Name,"",Opts) -> + setup_vector_variant(Name,"",Opts); +setup_extension(Name,Ext,Opts) -> + case get(Name) of + undefined -> + setup_vector_variant(Name,Ext,Opts); + OrigF = #func{} -> + F = get(Name++Ext), + case is_equal(F,OrigF) of + true -> + put(Name, OrigF#func{ext={ext,Ext}}), + skip; + _ -> + setup_vector_variant(Name,Ext,Opts) + end + end. + +setup_vector_variant(Name,Ext,Opts) -> + case reverse(Name) of + [$v|NoVec] -> %% Hmm might be a vector version + RealName = reverse(NoVec,Ext), + case get(RealName) of + undefined -> + setup_idx_binary(Name,Ext,Opts); + Real = #func{} -> + verify_args(Name,Ext,Real,RealName,Opts) + end; + _ -> + setup_idx_binary(Name,Ext,Opts) + end. + +verify_args(Name,Ext,Real = #func{params=RAs},RealName,Opts) -> + FuncName = Name ++ Ext, + Vector = #func{params=Args} = get(FuncName), + case is_vector(Name,Opts) of + false -> + Check = fun(#arg{type=#type{name=Type}},Acc) -> + if Type =:= Acc -> Acc; + Acc =:= undefined -> Type; + true -> different + end + end, + case foldl(Check,undefined,RAs) of + different -> + setup_idx_binary(Name,Ext,Opts); + undefined -> + setup_idx_binary(Name,Ext,Opts); + _ when length(Args) =/= 1 -> + setup_idx_binary(Name,Ext,Opts); + _Type -> + put(FuncName,Vector#func{where=erl,alt={vector,0,RealName}}), + put(RealName,Real#func{alt={has_vector,0,FuncName}}), + Name++Ext + end; + VecPos -> + put(FuncName,Vector#func{where=erl,alt={vector,VecPos,RealName}}), + put(RealName,Real#func{alt={has_vector,VecPos,FuncName}}), + Name++Ext + end. + +is_vector(Name, Opts) -> + Vecs = get_value(vector, Opts, []), + lookup(Name, Vecs, false). + +lookup(Name,[{Vector, VecPos}|R],Def) when is_list(Vector) -> + case lists:prefix(Vector,Name) of + true -> + %% VecPos; + %%io:format("~s ~s => ~p ~n", [Vector,Name,VecPos]), + case Vector == Name of + true -> + VecPos; + false -> %% Look for exactly the correct Name + case lookup(Name,R,Def) of + Def -> VecPos; + Other -> Other + end + end; + false -> lookup(Name,R, Def) + end; +lookup(Name,[_|R],Def) -> + lookup(Name,R,Def); +lookup(_,[], Def) -> Def. + +setup_idx_binary(Name,Ext,_Opts) -> + FuncName = Name ++ Ext, + Func = #func{params=Args} = get(FuncName), + Id = next_id(function), + + %% Ok warn if single is undefined + lists:foreach(fun(#arg{type=#type{base=memory}}) -> ok; + (#arg{type=#type{base=idx_binary}}) -> ok; + (#arg{type=#type{name="GLUquadric"}}) -> ok; + (A=#arg{type=#type{single=undefined}}) -> + ?warning("~p Unknown size of~n ~p~n", + [get(current_func),A]), + io:format("{~p, {~p, }}.~n", + [get(current_func),A#arg.name]), + ok; + (_) -> ok + end, Args), + + case setup_idx_binary(Args, []) of + ignore -> + put(FuncName, Func#func{id=Id}), + Name++Ext; + {bin, A1,A2} -> + put(FuncName, Func#func{id=Id,params=A1}), + Extra = FuncName++"Bin", + put(Extra, Func#func{params=A2, id=next_id(function)}), + [FuncName,Extra]; + {matrix, A1,A2} -> + put(FuncName, Func#func{id=Id,params=A2}), + Extra = FuncName++"Matrix", + put(Extra, Func#func{where=erl, params=A1, id=Id}), + [FuncName,Extra] + end. + +setup_idx_binary([A=#arg{in=true,type=T=#type{base=idx_binary}}|R], Acc) -> + A1 = A#arg{type=T#type{base=guard_int,size=4}}, + A2 = A#arg{type=T#type{base=binary}}, + Head = reverse(Acc), + case setup_idx_binary(R, []) of + ignore -> + {bin, Head ++ [A1|R], Head ++ [A2|R]}; + {bin, R1,R2} -> + {bin, Head ++ [A1|R1], Head ++ [A2|R2]} + end; +setup_idx_binary([A=#arg{in=true,type=T=#type{single={tuple,matrix}}}|R], Acc) -> + A1 = A#arg{type=T#type{single={tuple, matrix12}}}, + A2 = A#arg{type=T#type{single={tuple, 16}}}, + Head = reverse(Acc), + case setup_idx_binary(R, []) of + ignore -> + {matrix, Head ++ [A1|R], Head ++ [A2|R]}; + {matrix, R1,R2} -> + {matrix, Head ++ [A1|R1], Head ++ [A2|R2]} + end; +setup_idx_binary([H|R],Acc) -> + setup_idx_binary(R,[H|Acc]); +setup_idx_binary([],_) -> ignore. + +is_equal(F1=#func{type=T1,params=A1},F2=#func{type=T2,params=A2}) -> + Equal = is_equal_type(T1,T2) andalso is_equal_args(A1,A2), + case Equal of + true -> ok; + false -> + %% io:format("A1: ~p~nA2: ~p~n",[A1,A2]), + ?warning("Skipped Ext Not Equal ~p ~p~n", + [F1#func.name,F2#func.name]) + end, + Equal. + +is_equal_args([],[]) -> true; +is_equal_args([_A1=#arg{type=T1}|A1s],[_A2=#arg{type=T2}|A2s]) -> + case is_equal_type(T1,T2) of + true -> is_equal_args(A1s,A2s); + false -> + %%io:format("Diff~n ~p~n ~p ~n~n", [_A1,_A2]), + false + end. + +is_equal_type(T,T) -> true; +is_equal_type(#type{name="GLcharARB"},#type{name="GLchar"}) -> true; +%%is_equal_type(#type{name="GLhandleARB"},#type{name="GLuint"}) -> true; +is_equal_type(#type{name="GLenum"},#type{name="GLuint"}) -> true; +is_equal_type(#type{name="GLenum"},#type{name="GLint"}) -> true; +is_equal_type(#type{base=idx_binary},#type{base=guard_int}) -> true; +is_equal_type(#type{base=idx_binary},#type{base=memory}) -> true; +is_equal_type(#type{single={tuple,matrix}},#type{single={tuple,matrix12}}) -> true; +is_equal_type(#type{base=B,single=S,name=N,size=Sz}, + #type{base=B,single=S,name=N,size=Sz}) -> true; +is_equal_type(_,_) -> false. + +skip(Name,Opts) -> + Skip = get_value(skip, Opts, []), + lists:any(fun(Prefix) -> lists:prefix(Prefix,Name) end, Skip). + +keep(Name,Opts) -> + Skip = get_value(keep, Opts, []), + lists:any(fun(Prefix) -> lists:prefix(Prefix,Name) end, Skip). + +get_extension(ExtName,_Opts) -> + case reverse(ExtName) of + "BRA" ++ Name -> {reverse(Name),"ARB"}; + "TXE" ++ Name -> {reverse(Name),"EXT"}; + "ASEM" ++ Name -> {reverse(Name),"MESA"}; + "ITA" ++ Name -> {reverse(Name),"ATI"}; + "DMA" ++ Name -> {reverse(Name),"AMD"}; + "VN" ++ Name -> {reverse(Name),"NV"}; %Nvidia + "ELPPA"++ Name -> {reverse(Name),"APPLE"}; + "LETNI"++ Name -> {reverse(Name),"INTEL"}; + "NUS" ++ Name -> {reverse(Name),"SUN"}; + "XNUS" ++ Name -> {reverse(Name),"SUNX"}; + "IGS" ++ Name -> {reverse(Name),"SGI"}; + "SIGS" ++ Name -> {reverse(Name),"SGIS"}; + "XIGS" ++ Name -> {reverse(Name),"SGIX"}; + "XFD3" ++ Name -> {reverse(Name),"3DFX"}; + "MBI" ++ Name -> {reverse(Name),"IBM"}; + "RGNI" ++ Name -> {reverse(Name),"INGR"}; + "IGP" ++ Name -> {reverse(Name),"PGI"}; + "PH" ++ Name -> {reverse(Name),"HP"}; + "YDEMERG" ++ Name -> {reverse(Name),"GREMEDY"}; + %%["" ++ Name] -> {Name; %% + _ -> {ExtName, ""} + end. + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +drop_empty(List) -> + filter(fun(#xmlText { value = Text}) -> + string:strip(Text) =/= ""; + (_)-> + true + end, List). + +name(Name, _Opts) -> Name. + +next_id(What) -> + Next = case get(What) of + undefined -> 5010; %% Opengl + N -> N+1 + end, + put(What, Next), + Next. diff --git a/lib/wx/api_gen/gl_gen.hrl b/lib/wx/api_gen/gl_gen.hrl new file mode 100644 index 0000000000..0eef69b817 --- /dev/null +++ b/lib/wx/api_gen/gl_gen.hrl @@ -0,0 +1,41 @@ + +-record(func, + { + name = undefined, % real name + type = void, % method type + params = [], % arguments to the function + where = both, % C code and/or erlang + id = undefined, % Integer + alt = undefined, % Function alternative + ext = undefined % Have ARB or other extension + } + ). + +-record(arg, + { + name = undefined, + type = undefined, + in = true, + where = both, % both in c and erl or only in either + alt = undefined + }). + +-record(type, + { + name = undefined, % typename + base = undefined, % basename int, char, float .. + size = 4, % in bytes + by_val = true, % or false = by_ref + single = true, % Single or array (list) + ref = undefined, % {pointer, N} + mod = [] % const ... + } + ). + +-record(def, {name, val, type}). %% type=hex, int, string + +-define(error(What), + erlang:error({{?MODULE,?LINE},{get(current_func)},What})). + +-define(warning(Str,Args), + io:format("~p:~p Warning:"++Str, [?MODULE,?LINE] ++ Args)). diff --git a/lib/wx/api_gen/gl_gen_c.erl b/lib/wx/api_gen/gl_gen_c.erl new file mode 100644 index 0000000000..5c72499790 --- /dev/null +++ b/lib/wx/api_gen/gl_gen_c.erl @@ -0,0 +1,596 @@ +%% +%% %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 : gl_gen_c.erl +%%% Author : Dan Gudmundsson <[email protected]> +%%% Description : +%%% +%%% Created : 25 Apr 2007 by Dan Gudmundsson <[email protected]> +%%%------------------------------------------------------------------- + +-module(gl_gen_c). +-compile(export_all). + +-include("gl_gen.hrl"). + +-import(lists, [foldl/3,foldr/3,reverse/1, keysearch/3, map/2, filter/2, max/1]). +-import(gen_util, [lowercase/1, lowercase_all/1, uppercase/1, uppercase_all/1, + open_write/1, close/0, c_copyright/0, w/2, + args/3, strip_name/2]). +-import(wx_gen, [next_id/1]). + + +gen(GLFuncs, GLUFuncs) -> + gen_defines(GLFuncs,GLUFuncs), + gl_gen_init(GLFuncs), + glu_gen_init(GLUFuncs), + + %% Marshal funcs + open_write("../c_src/gen/gl_funcs.cpp"), + c_copyright(), + w("/***** This file is generated do not edit ****/ ~n~n", []), + w("#include <stdio.h>~n", []), + w("#include <string.h>~n", []), + w("#include \"../wxe_impl.h\"~n", []), + w("#include \"../wxe_gl.h\"~n", []), + w("#include \"gl_fdefs.h\"~n", []), + + w("~nint gl_error_op;~n", []), + w("void gl_dispatch(int op, char *bp,ErlDrvTermData caller,WXEBinRef *bins[]){~n", + []), + w(" gl_error_op = op;~n", []), + w(" if(caller != gl_active) {~n", []), + w(" wxGLCanvas * current = glc[caller];~n", []), + w(" if(current) { gl_active = caller; current->SetCurrent();}~n", []), + w(" else {~n " + " ErlDrvTermData rt[] = // Error msg~n" + " {ERL_DRV_ATOM, driver_mk_atom((char *) \"_wxe_error_\"),~n" + " ERL_DRV_INT, op,~n" + " ERL_DRV_ATOM, driver_mk_atom((char *) \"no_gl_context\"),~n" + " ERL_DRV_TUPLE,3};~n" + " driver_send_term(WXE_DRV_PORT,caller,rt,8);~n" + " return ;~n }~n };~n~n", []), + + w(" switch(op) ~n{~n",[]), + w(" case 5000: ~n wxe_tess_impl(bp, caller); ~n break;~n", []), + w(" case WXE_BIN_INCR:~n driver_binary_inc_refc(bins[0]->bin);~n break;~n",[]), + w(" case WXE_BIN_DECR:~n driver_binary_dec_refc(bins[0]->bin);~n break;~n",[]), + + [funcs(F) || F <- GLUFuncs], + [funcs(F) || F <- GLFuncs], + + w("}} /* The End */~n~n",[]), + + close(). + +funcs([F1|Fs]) when is_list(F1) -> + put(current_func,F1), + func(get(F1)), + erase(current_func), + funcs(Fs); +funcs([]) -> ok; +funcs(F) -> + put(current_func,F), + func(get(F)), + erase(current_func). + +func(#func{where=erl}) -> ok; +func(#func{id=Id,alt={has_vector,_,FuncName}}) -> + #func{name=Name,type=T,params=As} = get(FuncName), + w("case ~p: { // ~s ~n", [Id,Name]), + put(bin_count,-1), + As1 = declare_vars(T, As), + As2 = decode_args(As1), + As3 = call_gl(Name,T,As2), + build_return_vals(T,As3), + free_args(), + w("}; break; ~n", []); +func(#func{name=Name,id=Id,type=T,params=As,alt=_Alt}) -> + w("case ~p: { // ~s ~n", [Id,Name]), + put(bin_count,-1), + As2 = decode_args(As), + declare_vars(T, As), %% Unusal order but it's c++ + As3 = call_gl(Name,T,As2), + build_return_vals(T,As3), + free_args(), + w("}; break; ~n", []). + +declare_vars(void,Ps) -> + [declare_var(P) || P <- Ps]; +declare_vars(T, Ps) -> + declare_var(#arg{name="result",in=false,type=T}), + [declare_var(P) || P <- Ps]. + +declare_var(A=#arg{where=erl}) -> A; + +declare_var(A=#arg{name=N,in=false,type=#type{name=T,base=B,single={tuple,Sz}}}) -> + true = is_number(Sz), %% Assert + w(" ~s ~s[~p] = {~s};~n", [T,N,Sz,args(fun zero/1,",",lists:duplicate(Sz,B))]), + A; +declare_var(A=#arg{name=N,in=false,type=#type{name=T,base=B,single={list,Sz}}}) when is_number(Sz) -> + w(" ~s ~s[~p] = {~s};~n", [T,N,Sz,args(fun zero/1,",",lists:duplicate(Sz,B))]), + A; +declare_var(A=#arg{name=N,in=false,type=#type{name=T,single={list,ASz,_USz},mod=[]}}) -> + true = is_list(ASz), %% Assert + w(" ~s *~s;~n", [T,N]), + w(" ~s = (~s *) driver_alloc(sizeof(~s) * *~s);~n", [N,T,T,ASz]), + store_free(N), + A; +declare_var(A=#arg{name=N,in=false,type=#type{name=T,base=binary,size=Sz}}) -> + true = is_number(Sz), %% Assert + w(" ~s ~s[~p];~n", [T,N,Sz]), + A; +declare_var(A=#arg{name=N,in=false, + type=#type{name=T="GLUquadric",base=B,by_val=false,single=true}}) -> + A; +declare_var(A=#arg{name=N,in=false, + type=#type{name=T,base=B,by_val=false,single=true}}) -> + w(" ~s ~s[1] = {~s};~n", [T,N,zero(B)]), + A; +declare_var(A=#arg{where=_}) -> + A. + +zero(float) -> "0.0"; +zero(_) -> "0". + +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_args(As0) -> + {As,_Align} = lists:mapfoldl(fun decode_arg/2,0,As0), + As. + +decode_arg(P=#arg{where=erl},A) -> {P,A}; +decode_arg(P=#arg{where=c},A) -> {P,A}; +decode_arg(P=#arg{in=false},A) -> {P,A}; + +decode_arg(P=#arg{name=Name,type=#type{name=Type,base=binary}},A0) -> + w(" ~s *~s = (~s *) bins[~p]->base;~n", [Type,Name,Type,next_id(bin_count)]), + {P, A0}; +decode_arg(P=#arg{name=Name,type=#type{name=Type,base=memory}},A0) -> + w(" ~s *~s = (~s *) bins[~p]->base;~n", [Type,Name,Type,next_id(bin_count)]), + {P, A0}; +decode_arg(P=#arg{name=Name,type=#type{name=T,base=string,single=list}},A0) -> + A = align(4,A0), + w(" int * ~sLen = (int *) bp; bp += 4;~n", [Name]), + w(" int * ~sTotSize = (int *) bp; bp += 4;~n",[Name]), +%% w(" if(*~sLen > 256) *~sLen = 256;", []), + w(" ~s **~s;~n", [T,Name]), + w(" ~s = (~s **) driver_alloc(sizeof(~s *) * *~sLen); ~n",[Name, T, T, Name]), + store_free(Name), + w(" for(int i=0;i<*~sLen;i++) {~n", [Name]), + w(" ~s[i] = (~s *) bp; bp += 1+strlen(bp);};~n",[Name,T]), + w(" bp += (8 - ((~p + *~sTotSize) % 8)) % 8;~n",[A,Name]), + {P, 0}; + +decode_arg(P=#arg{name=Name,type=#type{size=Sz,single=list,name=Type}},A0) -> + A = align(max([Sz,4]),A0), + w(" int * ~sLen = (int *) bp; bp += ~p;~n", [Name, max([4,Sz])]), + w(" ~s * ~s = (~s *) bp; ", [Type,Name,Type]), + w(" bp += (8-((*~sLen*~p+~p)%8))%8;~n", [Name,Sz,A]), + {P, 0}; +decode_arg(P=#arg{name=Name,type=#type{size=TSz,name=Type,single={tuple,undefined}}},A0) -> + A = align(TSz,A0), + w(" int *~sLen = (int *) bp; bp += ~p;~n", [Name, max([4,TSz])]), + if TSz =:= 4 -> + w(" ~s *~s = (~s *) bp; bp += *~sLen*4+((*~sLen)+~p)%2*4;~n", + [Type,Name,Type, Name,Name, A div 4]); + TSz =:= 8 -> + w(" ~s *~s = (~s *) bp; bp += *~sLen*8;~n", [Type,Name,Type,Name]) + end, + {P, 0}; +decode_arg(P=#arg{name=Name,type=#type{size=BSz,name=Type,single={tuple,TSz}}},A0) -> + A = align(BSz,TSz,A0), + w(" ~s * ~s = (~s *) bp; bp += ~p;~n", [Type,Name,Type,BSz*TSz]), + {P, A}; +decode_arg(P=#arg{name=Name,type=#type{size=BSz,name=Type,single={list,TSz}}},A0) -> + A = align(BSz,TSz,A0), + w(" ~s * ~s = (~s *) bp; bp += ~p;~n", [Type,Name,Type,BSz*TSz]), + {P, A}; +decode_arg(P=#arg{name=Name,type=#type{name=Type,base=guard_int}},A0) -> + A = align(4,A0), + w(" ~s *~s = (~s *) * (int *) bp; bp += 4;~n", [Type,Name,Type]), + {P, A}; +decode_arg(P=#arg{name=Name,type=#type{name=Type,base=string,single=true}},A0) -> + w(" ~s *~s = (~s *) bp;~n", [Type,Name,Type]), + w(" int ~sLen = strlen((char *)~s); bp += ~sLen+1+((8-((1+~sLen+~p)%8))%8);~n", + [Name,Name,Name,Name,A0]), + {P, 0}; +decode_arg(P=#arg{name=Name, + type=#type{name=Type,size=8,base=int,by_val=true,ref=undefined}},A0) -> + A = align(8,A0), + w(" ~s ~s = (~s) * (GLuint64EXT *) bp; bp += 8;~n", [Type,Name,Type]), + {P, A}; +decode_arg(P=#arg{name=Name,type=#type{name=Type="GLUquadric",size=8,base=int}},A0) -> + A = align(8,A0), + w(" ~s * ~s = (~s *) * (GLuint64EXT *) bp; bp += 8;~n", [Type,Name,Type]), + {P, A}; +decode_arg(P=#arg{name=Name, + type=#type{name=Type,size=Sz,by_val=true,ref=undefined}},A0) -> + A = align(Sz,A0), + w(" ~s *~s = (~s *) bp; bp += ~p;~n", [Type,Name,Type,Sz]), + {P, A}; +decode_arg(P=#arg{name=Name,type=#type{size=BSz,name=Type,single={tuple_list,TSz}}},A0) -> + A = align(BSz,TSz,A0), + w(" int *~sLen = (int *) bp; bp += ~p;~n", [Name, max([4,BSz])]), + w(" ~s * ~s = (~s *) bp; bp += *~sLen*~p;~n", [Type,Name,Type,Name,BSz*TSz]), + {P, A}; +decode_arg(P=#arg{name=Name, type=#type{name=Type,size=Sz,by_val=false, + ref={pointer,1}, mod=[const]}}, + A0) -> + A = align(Sz,A0), + w(" ~s *~s = (~s *) bp; bp += ~p;~n", [Type,Name,Type,Sz]), + {P, A}; +decode_arg(P, _A) -> + ?error({unhandled_type, {P#arg.name,P#arg.type,_A}}). + +align(Size, PreAlign) -> + align(Size,1,PreAlign). + +align(1,N,A) -> (A+1*N+0) rem 8; + +align(2,N,A) when (A rem 2) =:= 0 -> (A+2*N+0) rem 8; +align(2,N,A) when (A rem 2) =:= 1 -> a_str(1),(A+2*N+1) rem 8; + +align(4,N,A) when (A rem 4) =:= 0 -> (A+4*N+0) rem 8; +align(4,N,A) when (A rem 4) =:= 1 -> a_str(3),(A+4*N+3) rem 8; +align(4,N,A) when (A rem 4) =:= 2 -> a_str(2),(A+4*N+2) rem 8; +align(4,N,A) when (A rem 4) =:= 3 -> a_str(1),(A+4*N+1) rem 8; + +align(8,_,0) -> 0; +align(8,_,1) -> a_str(7),0; +align(8,_,2) -> a_str(6),0; +align(8,_,3) -> a_str(5),0; +align(8,_,4) -> a_str(4),0; +align(8,_,5) -> a_str(3),0; +align(8,_,6) -> a_str(2),0; +align(8,_,7) -> a_str(1),0. + +a_str(P) -> w(" bp += ~p;~n", [P]). + +call_gl(Name,void,As) -> + Args = args(fun call_arg/1, ",", As), + w(" we~s(~s);~n", [Name,Args]), + As; +call_gl(Name,T=#type{},As) -> + Args = args(fun call_arg/1, ",", As), + Type = result_type(T), + w(" ~s result = we~s(~s);~n", [Type,Name,Args]), + As. + +result_type(#type{name=T, ref=undefined}) -> T; +result_type(#type{name=T, ref={pointer,1}, mod=Mods}) -> + mod(Mods) ++ T ++ " * ". + +call_arg(#arg{alt={length,Alt},type=#type{}}) -> + "*" ++ Alt ++ "Len"; +call_arg(#arg{alt={constant,Alt},type=#type{}}) -> + Alt; +call_arg(#arg{name=Name,type=#type{single={tuple, _}}}) -> + Name; +call_arg(#arg{name=Name,type=#type{single={list, _}}}) -> + Name; +call_arg(#arg{name=Name,type=#type{size=8,base=int,ref=undefined}}) -> + Name; +call_arg(#arg{name=Name,type=#type{ref=undefined}}) -> + "*" ++ Name; +call_arg(#arg{name=Name,type=#type{base=guard_int}}) -> + Name; +call_arg(#arg{name=Name,type=#type{base=string,ref={pointer,2},mod=[const]}}) -> + "(const GLchar **) " ++ Name; +call_arg(#arg{name=Name,type=#type{size=8,base=int,ref={pointer,1}}}) -> + Name; +call_arg(#arg{name=Name,type=#type{}}) -> + Name. + +build_return_vals(Type,As) -> + case calc_sizes(Type,As) of + {0,none,0} -> %% Sync memory access functions + Any = fun(#arg{type=#type{base=B}}) -> B =:= memory end, + case lists:any(Any, As) of + false -> ok; + true -> + w(" int AP = 0; ErlDrvTermData rt[6];~n",[]), + w(" rt[AP++]=ERL_DRV_ATOM;" + " rt[AP++]=driver_mk_atom((char *) \"_wxe_result_\");~n",[]), + w(" rt[AP++]=ERL_DRV_ATOM;" + " rt[AP++]=driver_mk_atom((char *) \"ok\");~n",[]), + w(" rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;~n",[]), + w(" driver_send_term(WXE_DRV_PORT,caller,rt,AP);~n",[]), + ok + end; + {Val,Vars,Cnt} -> + ExtraTuple = if Cnt > 1 -> 2; true -> 0 end, + CSize = if Vars =:= none -> + Sz = integer_to_list(Val+4+ExtraTuple), + w(" int AP = 0; ErlDrvTermData rt[~s];~n",[Sz]), + Sz; + true -> + Sz = integer_to_list(Val+4+ExtraTuple) ++ " + " ++ Vars, + w(" int AP = 0; ErlDrvTermData *rt;~n",[]), + w(" rt = (ErlDrvTermData *) " + "driver_alloc(sizeof(ErlDrvTermData)*(~s));~n", [Sz]), + Sz + end, + w(" rt[AP++]=ERL_DRV_ATOM; rt[AP++]=driver_mk_atom((char *) \"_wxe_result_\");~n",[]), + FreeList = build_ret_types(Type,As), + case Cnt of + 1 -> ok; + _ -> + w(" rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = ~p;~n",[Cnt]) + end, + w(" rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = 2;~n",[]), + w(" if (AP != ~s ) fprintf(stderr, \"%d: ERROR AP mismatch %d %d\\r\\n\",__LINE__,AP,~s);~n", + [CSize,CSize]), + w(" driver_send_term(WXE_DRV_PORT,caller,rt,AP);~n",[]), + case Vars of + none -> ignore; + _ -> + w(" driver_free(rt); ~n", []) + end, + [w(" ~s~n", [Name]) || Name <- FreeList], + ok + end. + +calc_sizes(Type,As) -> + TSz = case return_size("result", Type) of + {0, none} -> + {0, none, 0}; + {Sz,Vars} -> + {Sz,Vars, 1} + end, + Calc = fun(#arg{name=N,in=False,where=W,type=T},{Sz,Vars, Cnt}) + when False =/= true, W=/= c -> + case return_size(N, T) of + {Val, none} -> {Sz+Val, Vars, Cnt+1}; + {Val, Var} when Vars =:= none -> + {Sz+Val, Var,Cnt+1}; + {Val, Var} when Vars =:= none -> + {Sz+Val, Var ++ " + " ++ Vars,Cnt+1} + end; + (_,Acc) -> Acc + end, + foldl(Calc, TSz, As). + +return_size(_N,void) -> {0, none}; +return_size(_N,#type{base=binary}) -> {4, none}; +return_size(_N,#type{single=true}) -> {2,none}; +return_size(_N,#type{single={tuple,Sz}}) -> {Sz*2+2, none}; +return_size(_N,#type{name="GLubyte",single={list,null}}) ->{3, none}; +return_size(_N,#type{single={list,Sz}}) -> {Sz*2+3, none}; +return_size(_N,#type{base=string,single={list,_,_}}) -> {3, none}; +return_size(_N,#type{single={list,_,Sz}}) -> {3, "(*" ++Sz++")*2"}. + + +build_ret_types(void,Ps) -> + Calc = fun(#arg{name=N,in=False,where=W,type=T},Free) + when False =/= true, W=/= c -> + 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) -> + build_ret("result", out, Type), + Calc = fun(#arg{name=N,in=False,where=W,type=T},Free) + when False =/= true, W=/= c -> + case build_ret(N, False, T) of + ok -> Free; + Other -> [Other|Free] + end; + (_,Free) -> Free + end, + lists:foldl(Calc, [], Ps). + +build_ret(Name,_Q,#type{name=_T,base=int,single=true,by_val=true}) -> + w(" rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) ~s;~n", [Name]); +build_ret(Name,_Q,#type{name=_T,base=bool,single=true,by_val=true}) -> + w(" rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) ~s;~n", [Name]); +build_ret(Name,_Q,#type{name="GLUquadric",base=int}) -> + w(" rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) ~s;~n", [Name]); +build_ret(Name,_Q,#type{name=_T,base=int,single=true,by_val=false}) -> + w(" rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *~s;~n", [Name]); +build_ret(Name,_Q,#type{name=_T,base=bool,single=true,by_val=false}) -> + w(" rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *~s;~n", [Name]); +build_ret(Name,_Q,#type{name=_T,size=4,base=float,single=true,by_val=false}) -> + w(" GLdouble ~sConv = (double) *~s; \n",[Name,Name]), + w(" rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) &~sConv;~n", [Name]); +build_ret(Name,_Q,#type{name=_T,size=8,base=float,single=true,by_val=false}) -> + w(" rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) ~s;~n", [Name]); + +build_ret(Name,_Q,#type{name=_T,size=FSz,base=float,single={tuple,Sz}}) -> + Temp = Name ++ "Tmp", + case FSz of + 8 -> + w(" GLdouble *~s = ~s;\n", [Temp,Name]); + 4 -> + w(" GLdouble ~sConv[~p], *~s = ~sConv; \n",[Name,Sz,Temp,Name]), + w(" for(int i=0; i < ~p; i++) ~sConv[i] = (GLdouble) ~s[i];\n",[Sz,Name,Name]) + end, + [w(" rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) ~s++;~n", [Temp]) + || _ <- lists:seq(1,Sz)], + w(" rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = ~p;~n",[Sz]); +build_ret(Name,_Q,#type{name=T,base=_,single={tuple,Sz}}) -> + Temp = Name ++ "Tmp", + w(" ~s *~s = ~s;\n", [T,Temp,Name]), + [w(" rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *~s++;~n", [Temp]) + || _ <- lists:seq(1,Sz)], + w(" rt[AP++] = ERL_DRV_TUPLE; rt[AP++] = ~p;~n",[Sz]); +build_ret(Name,_Q,#type{name="GLubyte",single={list,null}}) -> + w(" rt[AP++] = ERL_DRV_STRING; rt[AP++] = (ErlDrvTermData) ~s;" + " rt[AP++] = strlen((char *) ~s);\n", [Name, Name]); +build_ret(Name,_Q,#type{base=string,single={list,_,Sz}}) -> + w(" rt[AP++] = ERL_DRV_STRING; rt[AP++] = (ErlDrvTermData) ~s;" + " rt[AP++] = *~s;\n", [Name, Sz]); +build_ret(Name,_Q,#type{name=_T,base=B,single={list,_,Sz}}) when B =/= float -> + w(" for(int i=0; i < *~s; i++) {\n", [Sz]), + w(" rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) ~s[i];}~n", [Name]), + w(" rt[AP++] = ERL_DRV_NIL;", []), + w(" rt[AP++] = ERL_DRV_LIST; rt[AP++] = (*~s)+1;~n",[Sz]); +build_ret(Name,_Q,#type{name=_T,size=FSz,base=float,single={list,Sz}}) -> + Temp = Name ++ "Tmp", + case FSz of + 8 -> + w(" GLdouble *~s = ~s;\n", [Temp,Name]); + 4 -> + w(" GLdouble ~sConv[~p], *~s = ~sConv; \n",[Name,Sz,Temp,Name]), + w(" for(int i=0; i < ~p; i++) ~sConv[i] = (GLdouble) ~s[i];\n",[Sz,Name,Name]) + end, + [w(" rt[AP++] = ERL_DRV_FLOAT; rt[AP++] = (ErlDrvTermData) ~s++;~n", [Temp]) + || _ <- lists:seq(1,Sz)], + w(" rt[AP++] = ERL_DRV_NIL;", []), + w(" rt[AP++] = ERL_DRV_LIST; rt[AP++] = ~p+1;~n",[Sz]); +build_ret(Name,_Q,#type{name=T,base=_,single={list,Sz}}) -> + Temp = Name ++ "Tmp", + w(" ~s *~s = ~s;\n", [T,Temp,Name]), + [w(" rt[AP++] = ERL_DRV_INT; rt[AP++] = (ErlDrvSInt) *~s++;~n", [Temp]) + || _ <- lists:seq(1,Sz)], + w(" rt[AP++] = ERL_DRV_NIL;", []), + w(" rt[AP++] = ERL_DRV_LIST; rt[AP++] = ~p+1;~n",[Sz]); +build_ret(Name,_Q,#type{name="GLubyte",base=binary,size=Sz}) -> + w(" ErlDrvBinary * BinCopy = driver_alloc_binary(~p);~n", [Sz]), + w(" memcpy(BinCopy->orig_bytes, ~s, ~p);~n", [Name,Sz]), + w(" rt[AP++] = ERL_DRV_BINARY; rt[AP++] = (ErlDrvTermData) BinCopy;", []), + w(" rt[AP++] = ~p; rt[AP++] = 0;~n", [Sz]), + "driver_free_binary(BinCopy);"; +build_ret(Name,_Q,T=#type{}) -> + io:format("{~p, {~p, {single,{tuple,X}}}}.~n", [get(current_func),Name]), + io:format(" ~p~n",[T]). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +gen_defines(GLFuncs,GLUFuncs) -> + open_write("../c_src/gen/gl_fdefs.h"), + c_copyright(), + w("/***** This file is generated do not edit ****/ ~n~n", []), + w("#ifdef WX_DEF_EXTS~n", []), + w("# define WXE_EXTERN~n", []), + w("#else~n# define WXE_EXTERN extern~n", []), + w("#endif~n~n", []), + [fdefs(F) || F <- GLFuncs], + [fdefs(F) || F <- GLUFuncs], + close(). + +fdefs([F1|_Fs]) when is_list(F1) -> + put(current_func,F1), + fdef(get(F1)), + erase(current_func); +fdefs([]) -> ok; +fdefs(F) -> + put(current_func,F), + fdef(get(F)), + erase(current_func). + +fdef(#func{where=erl}) -> ok; +fdef(#func{alt={has_vector,_,FuncName}}) -> + #func{name=Name,type=T,params=As} = get(FuncName), + w("typedef ~s (APIENTRY * WXE~s)(~s);~n", + [fdef_type(T), uppercase_all(Name), fdef_types(As)]), + w("WXE_EXTERN WXE~s we~s;~n", [uppercase_all(Name), Name]); +fdef(#func{name=Name,type=T,params=As,alt=_Alt}) -> + w("typedef ~s (APIENTRY * WXE~s)(~s);~n", + [fdef_type(T), uppercase_all(Name), fdef_types(As)]), + w("WXE_EXTERN WXE~s we~s;~n", [uppercase_all(Name), Name]). + +fdef_type(void) -> "void"; +fdef_type(#type{name=T, mod=Mod, single=true, ref=undefined}) -> + mod(Mod) ++ T; +fdef_type(#type{name=T, mod=Mod, single={tuple,Sz}, ref=undefined}) -> + mod(Mod) ++ T ++ " m[" ++ integer_to_list(Sz) ++ "]"; +fdef_type(#type{name=T, mod=Mod, ref={pointer,1}}) -> + mod(Mod) ++ T ++ " *"; +fdef_type(#type{name=T, mod=Mod, ref={pointer,2}}) -> + mod(Mod) ++ T ++ " **". + +mod([const]) -> "const "; +mod([]) -> "". + +fdef_types(As) -> + args(fun(#arg{type=T}) -> fdef_type(T) end, ",", As). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +gl_gen_init(Funcs) -> + open_write("../c_src/gen/gl_finit.h"), + c_copyright(), + w("/***** This file is generated do not edit ****/ ~n~n", []), + w("static struct {\n" + " const char * name;\n" + " const char * alt;\n" + " void * func;\n" + "} gl_fns[] = \n" + "{\n", []), + [finits(F) || F <- Funcs], + w(" { NULL, NULL, NULL}};\n",[]), + close(). + +glu_gen_init(Funcs) -> + open_write("../c_src/gen/glu_finit.h"), + c_copyright(), + w("/***** This file is generated do not edit ****/ ~n~n", []), + w("static struct {\n" + " const char * name;\n" + " const char * alt;\n" + " void * func;\n" + "} glu_fns[] = \n" + "{\n", []), + [finits(F) || F <- Funcs], + w(" { NULL, NULL, NULL}};\n",[]), + close(). + + +finits([F1|_Fs]) when is_list(F1) -> + put(current_func,F1), + finit(get(F1)), + erase(current_func); +finits([]) -> ok; +finits(F) -> + put(current_func,F), + finit(get(F)), + erase(current_func). + +finit(#func{where=erl}) -> ok; +finit(#func{alt={has_vector,_,FuncName}, ext=Ext}) -> + #func{name=Name} = get(FuncName), + w(" {~p, ~s, &we~s},\n", [Name, ext(Name,Ext), Name]); +finit(#func{name=Name, ext=Ext}) -> + w(" {~p, ~s, &we~s},\n", [Name, ext(Name,Ext), Name]). + +ext(Name, {ext,Ext}) -> + "\"" ++ Name ++ Ext ++ "\""; +ext(_,_) -> "NULL". + + + + + diff --git a/lib/wx/api_gen/gl_gen_erl.erl b/lib/wx/api_gen/gl_gen_erl.erl new file mode 100644 index 0000000000..3e436100b6 --- /dev/null +++ b/lib/wx/api_gen/gl_gen_erl.erl @@ -0,0 +1,603 @@ +%% +%% %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 : gl_gen_erl.erl +%%% Author : Dan Gudmundsson <[email protected]> +%%% Description : +%%% +%%% Created : 18 Apr 2007 by Dan Gudmundsson <[email protected]> +%%%------------------------------------------------------------------- +-module(gl_gen_erl). + +-include("gl_gen.hrl"). + +-compile(export_all). + +-import(lists, [foldl/3,foldr/3,reverse/1, keysearch/3, map/2, filter/2, max/1]). +-import(gen_util, [lowercase/1, lowercase_all/1, uppercase/1, uppercase_all/1, + open_write/1, close/0, erl_copyright/0, w/2, + args/3, args/4, strip_name/2]). + +gl_defines(Defs) -> + open_write("../include/gl.hrl"), + erl_copyright(), + w("~n%% OPENGL DEFINITIONS~n~n", []), + w("%% This file is generated DO NOT EDIT~n~n", []), + [gen_define(Def) || Def=#def{} <- Defs], + close(), + ok. + +glu_defines(Defs) -> + open_write("../include/glu.hrl"), + erl_copyright(), + w("~n%% GLU DEFINITIONS~n~n", []), + w("%% This file is generated DO NOT EDIT~n~n", []), + [gen_define(Def) || Def=#def{} <- Defs], + close(), + ok. + +gen_define(#def{name=N, val=Val, type=int}) -> + w("-define(~s, ~p).~n", [N,Val]); +gen_define(#def{name=N, val=Val, type=hex}) -> + w("-define(~s, ~.16#).~n", [N,Val]); +gen_define(#def{name=N, val=Val, type=string}) -> + w("-define(~s, ?~s).~n", [N,Val]). + +types() -> + [{"GLenum", "32/native-unsigned"}, + {"GLboolean", "8/native-unsigned"}, + {"GLbitfield","32/native-unsigned"}, % + %%{"GLvoid",":void "},% + {"GLbyte", "8/native-signed"}, % 1-byte signed + {"GLshort", "16/native-signed"}, % 2-byte signed + {"GLint", "32/native-signed"}, % 4-byte signed + {"GLubyte", "8/native-unsigned"}, % 1-byte unsigned + {"GLushort", "16/native-unsigned"}, % 2-byte unsigned + {"GLuint", "32/native-unsigned"}, % 4-byte unsigned + {"GLsizei", "32/native-signed"}, % 4-byte signed + {"GLfloat", "32/native-float"}, % single precision float + {"GLclampf", "32/native-float"}, % single precision float in [0,1] + {"GLdouble", "64/native-float"}, % double precision float + {"GLclampd", "64/native-float"}, % double precision float in [0,1] + {"GLsizeiptr","64/native-unsigned"}, % 64 bits int, convert on c-side + {"GLintptr", "64/native-unsigned"}, % 64 bits int, convert on c-sidew + {"GLUquadric", "64/native-unsigned"},% Handle 32bits aargh 64bits on mac64 + {"GLhandleARB","64/native-unsigned"} % Handle 32bits aargh 64bits on mac64 + ]. + +gl_api(Fs) -> + open_write("../src/gen/gl.erl"), + erl_copyright(), + w("~n%% OPENGL API~n~n", []), + w("%% This file is generated DO NOT EDIT~n~n", []), + w("%% @doc Standard OpenGL api. ~n", []), + w("%% See <a href=\"http://www.opengl.org/sdk/docs/man/\">www.opengl.org</a>~n",[]), + w("%%~n", []), + w("%% Booleans are represented by integers 0 and 1. ~n~n", []), + w("%% @type wx_mem(). see wx.erl on memory allocation functions~n", []), + w("%% @type enum(). An integer defined in gl.hrl~n", []), + w("%% @type offset(). An integer which is an offset in an array~n", []), + w("%% @type clamp(). A float clamped between 0.0 - 1.0 ~n", []), + + w("-module(gl).~n~n",[]), + w("-compile(inline).~n", []), + %% w("-compile(export_all).~n~n", []), + %% w("-compile(binary_comprehension).~n~n", []), + w("-include(\"wxe.hrl\").~n", []), + [w("-define(~s,~s).~n", [GL,Erl]) || {GL,Erl} <- types()], + + Exp = fun(F) -> gen_export(F) end, + ExportList = lists:map(Exp,Fs), + w("~n-export([~s]).~n~n", [args(fun(EF) -> EF end, ",", ExportList, 60)]), + + w("~n%% API ~n~n", []), + [gen_funcs(F) || F <- Fs], + close(), + ok. + +glu_api(Fs) -> + open_write("../src/gen/glu.erl"), + erl_copyright(), + w("~n%% OPENGL UTILITY API~n~n", []), + w("%% This file is generated DO NOT EDIT~n~n", []), + w("%% @doc A part of the standard OpenGL Utility api. ~n", []), + w("%% See <a href=\"http://www.opengl.org/sdk/docs/man/\">www.opengl.org</a>~n",[]), + w("%%~n", []), + w("%% Booleans are represented by integers 0 and 1. ~n~n", []), + w("%% @type wx_mem(). see wx.erl on memory allocation functions~n", []), + w("%% @type enum(). An integer defined in gl.hrl~n", []), + w("%% @type offset(). An integer which is an offset in an array~n", []), + w("%% @type clamp(). A float clamped between 0.0 - 1.0 ~n~n", []), + + w("-module(glu).~n",[]), + w("-compile(inline).~n", []), + w("-include(\"wxe.hrl\").~n", []), + [w("-define(~s,~s).~n", [GL,Erl]) || {GL,Erl} <- types()], + + Exp = fun(F) -> gen_export(F) end, + ExportList = ["tesselate/2" | lists:map(Exp,Fs)], + w("~n-export([~s]).~n~n", [args(fun(EF) -> EF end, ",", ExportList, 60)]), + + w("~n%% API ~n~n", []), + + w("%% @spec (Vec3, [Vec3]) -> {Triangles, VertexPos}~n",[]), + w("%% Vec3 = {float(),float(),float()}~n",[]), + w("%% Triangles = [VertexIndex::integer()]~n",[]), + w("%% VertexPos = binary()~n",[]), + w("%% @doc General purpose polygon triangulation.~n",[]), + w("%% The first argument is the normal and the second a list of~n" + "%% vertex positions. Returned is a list of indecies of the vertices~n" + "%% and a binary (64bit native float) containing an array of ~n" + "%% vertex positions, it starts with the vertices in Vs and ~n" + "%% may contain newly created vertices in the end.~n", []), + + w("tesselate({Nx,Ny,Nz}, Vs) ->~n",[]), + w(" wxe_util:call(5000, <<(length(Vs)):32/native,0:32,~n" + " Nx:?GLdouble,Ny:?GLdouble,Nz:?GLdouble,~n" + " (<< <<Vx:?GLdouble,Vy:?GLdouble,Vz:?GLdouble >>~n" + " || {Vx,Vy,Vz} <- Vs>>)/binary >>).~n~n", []), + + [gen_funcs(F) || F <- Fs], + close(), + ok. + +gen_funcs([F]) when is_list(F) -> + put(current_func,F), + gen_func(get(F)), + erase(current_func), + w(".~n~n",[]); +gen_funcs(All=[F|Fs]) when is_list(F) -> + put(current_func,F), + gen_doc([get(A) || A <- All]), + gen_func(get(F)), + erase(current_func), + w(";~n",[]), + gen_funcs(Fs); +gen_funcs([]) -> + w(".~n~n",[]); +gen_funcs(F) -> + put(current_func,F), + gen_doc([get(F)]), + gen_func(get(F)), + erase(current_func), + w(".~n~n",[]). + +gen_export([F|_]) when is_list(F) -> + gen_export2(get(F)); +gen_export(F) when is_list(F) -> + gen_export2(get(F)). + +gen_export2(#func{name=Name,alt={vector,VecPos,Vec}}) -> + #func{params=As0} = get(Vec), + {As1,_As2} = lists:split(VecPos, As0), + Args = lists:filter(fun(Arg) -> func_arg(Arg) =/= skip end, As1), + erl_func_name(Name) ++ "/" ++ integer_to_list(length(Args) +1); +gen_export2(#func{name=Name,params=As0}) -> + Args = lists:filter(fun(Arg) -> func_arg(Arg) =/= skip end, As0), + erl_func_name(Name) ++ "/" ++ integer_to_list(length(Args)). + + +gen_doc([#func{alt={vector,VecPos,Vec}}]) -> + #func{type=T,params=As} = get(Vec), + {As1,As2} = lists:split(VecPos, As), + Args1 = case args(fun func_arg/1, ",", As1) of [] -> []; Else -> Else++"," end, + Args2 = args(fun func_arg/1, ",", As2), + w("%% @spec (~s{~s}) -> ~s~n",[Args1,Args2,doc_return_types(T,As)]), + w("%% @equiv ~s(~s)~n",[erl_func_name(Vec), Args1++Args2]); +gen_doc([#func{name=Name,type=T,params=As,alt=Alt}|_]) -> + w("%% @spec (~s) -> ~s~n", [doc_arg_types(As),doc_return_types(T,As)]), + GLDoc = "http://www.opengl.org/sdk/docs/man/xhtml/", + w("%% @doc See <a href=\"~s~s.xml\">external</a> documentation.~n", + [GLDoc, doc_name(Name,Alt)]). + +gen_func(#func{name=Name,alt={vector,VecPos,Vec}}) -> + #func{params=As} = get(Vec), + {As1,As2} = lists:split(VecPos, As), + Args1 = case args(fun func_arg/1, ",", As1) of [] -> []; Else -> Else++"," end, + Args2 = args(fun func_arg/1, ",", As2), + + w("~s(~s{~s}) ->", [erl_func_name(Name),Args1,Args2]), + w(" ~s(~s)", [erl_func_name(Vec), Args1++Args2]); +gen_func(_F=#func{name=Name,type=T,params=As,id=MId}) -> + Args = args(fun func_arg/1, ",", As), + w("~s(~s)~s ", [erl_func_name(Name), Args, guard_test(As)]), + w("->~n", []), + PreAs = pre_marshal(As), + {StrArgs,_} = marshal_args(PreAs), + case have_return_vals(T,As) of + true -> + w(" wxe_util:call(~p, <<~s>>)", [MId, StrArgs]); + false -> + w(" wxe_util:cast(~p, <<~s>>)", [MId, StrArgs]) + end. + +func_arg(#arg{in=In,where=W,name=Name,type=Type}) + when In =/= false, W =/= c -> + case Type of + #type{single={tuple,TSz0}} when TSz0 =/= undefined -> + TSz = if is_integer(TSz0) -> TSz0; + TSz0 =:= matrix12 -> 12 + end, + [NameId|_] = erl_arg_name(Name), + Names = [[NameId|integer_to_list(Id)] || Id <- lists:seq(1,TSz)], + "{" ++ args(fun(ElName) -> ElName end, ",", Names) ++ "}"; + _ -> + erl_arg_name(Name) + end; +func_arg(_) -> skip. + +doc_arg_types(Ps0) -> + Ps = [P || P=#arg{in=In, where=Where} <- Ps0,In =/= false, Where =/= c], + args(fun doc_arg_type/1, ",", Ps). + +doc_return_types(T, Ps0) -> + Ps = [P || P=#arg{in=In, where=Where} <- Ps0,In =/= true, Where =/= c], + doc_return_types2(T, Ps). + +doc_return_types2(void, []) -> "ok"; +doc_return_types2(void, [#arg{type=T}]) -> doc_arg_type2(T); +doc_return_types2(T, []) -> doc_arg_type2(T); +doc_return_types2(void, Ps) -> + "{" ++ args(fun doc_arg_type/1,",",Ps) ++ "}"; +doc_return_types2(T, Ps) -> + "{" ++ doc_arg_type2(T) ++ "," ++ args(fun doc_arg_type/1,",",Ps) ++ "}". + +doc_arg_type(#arg{name=Name,type=T}) -> + try + erl_arg_name(Name) ++ "::" ++ doc_arg_type2(T) + catch _:Error -> + io:format("Error: ~p ~p~n~p~n",[Name, Error, erlang:get_stacktrace()]), + exit(error) + end. + +doc_arg_type2(T=#type{single=true}) -> + doc_arg_type3(T); +doc_arg_type2(T=#type{single=undefined}) -> + doc_arg_type3(T); +doc_arg_type2(T=#type{single={tuple,undefined}}) -> + "{" ++ doc_arg_type3(T) ++ "}"; +doc_arg_type2(T=#type{single={tuple,_Sz}}) -> + "{" ++ doc_arg_type3(T) ++ "}"; +doc_arg_type2(T=#type{single=list}) -> + "[" ++ doc_arg_type3(T) ++ "]"; +doc_arg_type2(T=#type{single={list, Max}}) when is_integer(Max) -> + "[" ++ doc_arg_type3(T) ++ "]"; +doc_arg_type2(_T=#type{single={list,null}}) -> + "string()"; +doc_arg_type2(T=#type{base=string}) -> + doc_arg_type3(T); +doc_arg_type2(T=#type{single={list,_,_}}) -> + "[" ++ doc_arg_type3(T) ++ "]"; +doc_arg_type2(T=#type{single={tuple_list,_TSz}}) -> + "[{" ++ doc_arg_type3(T) ++ "}]". + +doc_arg_type3(#type{name="GLenum"}) -> "enum()"; +doc_arg_type3(#type{name="GLclamp"++_}) -> "clamp()"; +doc_arg_type3(#type{base=int}) -> "integer()"; +doc_arg_type3(#type{base=float}) -> "float()"; +doc_arg_type3(#type{base=guard_int}) -> "offset()|binary()"; +doc_arg_type3(#type{base=string}) -> "string()"; +doc_arg_type3(#type{base=bool}) -> "0|1"; +doc_arg_type3(#type{base=binary}) -> "binary()"; +doc_arg_type3(#type{base=memory}) -> "wx:wx_mem()". + +guard_test(As) -> + Str = args(fun(#arg{name=N,type=#type{base=guard_int}}) -> + " is_integer("++erl_arg_name(N)++")"; + (_) -> + skip + end, ",", As), + case Str of + [] -> []; + Other -> " when " ++ Other + end. + +pre_marshal([#arg{name=N,in=true,type=#type{base=binary}}|R]) -> + w(" wxe_util:send_bin(~s),~n", [erl_arg_name(N)]), + pre_marshal(R); +pre_marshal([#arg{name=N,type=#type{base=memory}}|R]) -> + w(" wxe_util:send_bin(~s#wx_mem.bin),~n", [erl_arg_name(N)]), + pre_marshal(R); +pre_marshal([A=#arg{name=N,type=#type{base=string,single=list}}|R]) -> + %% With null terminations + w(" ~sTemp = list_to_binary([[Str|[0]] || Str <- ~s ]),~n", + [erl_arg_name(N), erl_arg_name(N)]), + [A|pre_marshal(R)]; +pre_marshal([A|R]) -> + [A|pre_marshal(R)]; +pre_marshal([]) -> []. + +marshal_args(As) -> + marshal_args(As, [], 0). + +marshal_args([#arg{where=erl}|Ps], Margs, Align) -> + marshal_args(Ps, Margs, Align); +marshal_args([#arg{where=c}|Ps], Margs, Align) -> + marshal_args(Ps, Margs, Align); +marshal_args([#arg{in=false}|Ps], Margs, Align) -> + marshal_args(Ps, Margs, Align); +marshal_args([#arg{name=Name, type=Type}|Ps], Margs, Align0) -> + {Arg,Align} = marshal_arg(Type,erl_arg_name(Name),Align0), + marshal_args(Ps, [Arg|Margs], Align); +marshal_args([],Margs, Align) -> + {args(fun(Str) -> Str end, ",", reverse(Margs)), Align}. + +marshal_arg(#type{size=Sz,name=Type,single={tuple,undefined}},Name,A0) -> + KeepA = case Sz of 8 -> "0:32,"; _ -> "" end, + Str0 = "(size("++Name++")):?GLuint,"++KeepA++"\n" + " (<< <<C:?"++Type++ ">> ||" + "C <- tuple_to_list("++Name++")>>)/binary", + case Sz of + 4 -> + {Str,Align} = align(4,A0,Str0), + {Str++",0:((("++integer_to_list(Align div 4)++ + "+size("++Name++")) rem 2)*32)",0}; + 8 -> + align(8,A0,Str0) + end; +marshal_arg(#type{size=BSz,name=Type,single={tuple,TSz}},Name,A0) + when is_integer(TSz) -> + NameId = hd(Name), + Names = [[NameId|integer_to_list(Id)] || Id <- lists:seq(1,TSz)], + All = args(fun(ElName) -> ElName ++ ":?" ++ Type end, ",", Names), + align(BSz,TSz,A0,All); + +marshal_arg(#type{size=BSz,name=Type,single={tuple,matrix12}},Name,A0) -> + NameId = hd(Name), + Ns0 = [[NameId|integer_to_list(Id)] || Id <- lists:seq(1,3)], + Ns1 = [[NameId|integer_to_list(Id)] || Id <- lists:seq(4,6)], + Ns2 = [[NameId|integer_to_list(Id)] || Id <- lists:seq(7,9)], + Ns3 = [[NameId|integer_to_list(Id)] || Id <- lists:seq(10,12)], + All = args(fun(ElName) -> ElName ++ ":?" ++ Type end, ",", + Ns0 ++ ["0"] ++ Ns1 ++ ["0"] ++ Ns2 ++ ["0"] ++ Ns3 ++ ["1"]), + align(BSz,16,A0,All); + +marshal_arg(#type{size=Sz,name=Type,base=Base,single=list},Name,A0) + when Base =:= float; Base =:= int -> + KeepA = case Sz of 8 -> "0:32,"; _ -> "" end, + Str0 = "(length("++Name++")):?GLuint,"++KeepA++"\n" + " (<< <<C:?"++Type++">> || C <- "++Name++">>)/binary", + {Str,Align} = align(max([Sz,4]),A0,Str0), + align_after(Sz,Align,0,1,Name,Str); + +marshal_arg(#type{base=guard_int},Name,A0) -> + align(4,A0,Name ++ ":?GLuint"); + +marshal_arg(#type{size=Sz,name=Type,single=true, + by_val=true,ref=undefined},Name,A0) -> + align(Sz,A0,Name ++ ":?" ++ Type); + +marshal_arg(#type{size=8,name="GLUquadric"=Type},Name,A0) -> + align(8,A0,Name ++ ":?" ++ Type); + +marshal_arg(#type{base=string,single=true,ref={pointer,1}},Name,A0) -> + Str = "(list_to_binary(["++Name++"|[0]]))/binary", % Null terminate + align_after(1,A0,1,1,Name,Str); + +marshal_arg(#type{base=string,single=list,ref={pointer,2}},Name,A0) -> + Str0 = + "(length("++Name++")):?GLuint," + "(size("++Name ++ "Temp)):?GLuint," + "(" ++ Name ++ "Temp)/binary", + {Str,A} = align(4,A0,Str0), + {Str ++ ",0:((8-((size("++Name++"Temp)+"++ + integer_to_list(A) ++") rem 8)) rem 8)", 0}; + +marshal_arg(#type{size=Sz,name=Type,single={tuple_list,TSz}},Name,A0) -> + NameId = hd(Name), + Names = [[NameId|integer_to_list(Id)] || Id <- lists:seq(1,TSz)], + TTup = args(fun(ElName) -> ElName end, ",", Names), + TBin = args(fun(ElName) -> ElName ++ ":?" ++ Type end, ",", Names), + + KeepA = case Sz of 8 -> "0:32,"; 4 -> "" end, + Str0 = "(length("++Name++")):?GLuint,"++KeepA++"\n" + " (<< <<"++TBin++">> || {"++TTup++"} <- "++Name++">>)/binary", + align(Sz,A0,Str0); + +marshal_arg(T=#type{}, Name, Align) -> + io:format("{\"~s\", {\"~s\", }}.~n", [get(current_func),lowercase(Name)]), + %%?error({unhandled_type, {Name,T}}). + w(" Don't know how to marshal this type ~p ~p ~n", [T,Name]), + align(8,Align,""). + +% Make sure that it is aligned before adding it, and update alignment +align(Size, PreAlign, Str) -> + align(Size,1,PreAlign,Str). + +align(1,N,A,Str) -> {Str, (A+1*N+0) rem 8}; + +align(2,N,A,Str) when (A rem 2) =:= 0 -> {Str, (A+2*N+0) rem 8}; +align(2,N,A,Str) when (A rem 2) =:= 1 -> {"0:8," ++Str, (A+2*N+1) rem 8}; + +align(4,N,A,Str) when (A rem 4) =:= 0 -> {Str, (A+4*N+0) rem 8}; +align(4,N,A,Str) when (A rem 4) =:= 1 -> {"0:24,"++Str, (A+4*N+3) rem 8}; +align(4,N,A,Str) when (A rem 4) =:= 2 -> {"0:16,"++Str, (A+4*N+2) rem 8}; +align(4,N,A,Str) when (A rem 4) =:= 3 -> {"0:8," ++Str, (A+4*N+1) rem 8}; + +align(8,_,0,Str) -> {Str, 0}; +align(8,_,1,Str) -> {"0:56,"++Str, 0}; +align(8,_,2,Str) -> {"0:48,"++Str, 0}; +align(8,_,3,Str) -> {"0:40,"++Str, 0}; +align(8,_,4,Str) -> {"0:32,"++Str, 0}; +align(8,_,5,Str) -> {"0:24,"++Str, 0}; +align(8,_,6,Str) -> {"0:16,"++Str, 0}; +align(8,_,7,Str) -> {"0:8," ++Str, 0}. + +align_after(8,0,_Add,_Multiplier,_Name,Str) -> {Str,0}; +align_after(4,0,Add,Mult,Name,Str) -> + Extra = extra_align(Add,Mult), + Align = ",0:(((length("++Name++")"++Extra++") rem 2)*32)", + {Str ++ Align,0}; +align_after(4,4,Add,Mult,Name,Str) -> + Extra = extra_align(Add,Mult), + Align = ",0:(((1+length("++Name++")"++Extra++") rem 2)*32)", + {Str ++ Align,0}; +align_after(2,A,Add,Mult,Name,Str) when (A rem 2) =:= 0 -> + Extra = extra_align(A+Add*2,Mult), + Align = ",0:((8-((length("++Name++")*2"++Extra++") rem 8)) rem 8)", + {Str ++ Align,0}; +align_after(1,A,Add,Mult,Name,Str) -> + Extra = extra_align(A+Add,Mult), + Align = ",0:((8-((length("++Name++")"++Extra++") rem 8)) rem 8)", + {Str ++ Align,0}; +align_after(Sz,A,Add,Mult,Name,Str) -> + io:format("~p ~p with ~p ~p ~s~n, ~p", [Sz,A,Add,Mult,Name,Str]), + ?error(align_error). + +extra_align(0,1) -> ""; +extra_align(0,M) when M > 1 -> "* " ++ integer_to_list(M); +extra_align(A,1) when A > 0 -> "+ " ++ integer_to_list(A); +extra_align(A,M) when A > 0,M>1 -> + "* " ++ integer_to_list(M) ++ "+ " ++ integer_to_list(A). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +have_return_vals(void, Ps) -> + lists:any(fun(#arg{in=In, type=#type{base=B}}) -> + In =/= true orelse B =:= memory + end, Ps); +have_return_vals(#type{}, _) -> true. + +erl_func_name("glu" ++ Name) -> check_name(lowercase(Name)); +erl_func_name("gl" ++ Name) -> check_name(lowercase(Name)). + +erl_arg_name(Name) -> uppercase(Name). + +check_name("begin") -> "'begin'"; +check_name("end") -> "'end'"; +check_name(Other) -> Other. + + +doc_name(Name0, Alt) -> + Name = doc_name2(Name0,Alt), +%% case lists:member(lists:last(Name0), "uvbisdf987654312") of +%% true -> io:format("~s ~s~n", [Name0,Name]); +%% false -> ignore +%% end, + Name. + +doc_name2(N="glGetBufferParameteriv", _) -> N; +doc_name2(N="glEnd", _) -> N; +doc_name2(Name, {has_vector,_,_}) -> + strip_hard(reverse(Name)); +doc_name2(Name, _) -> + reverse(strip(reverse(Name))). + +strip_hard(Rev) -> + case strip(Rev) of + Rev -> reverse(strip2(Rev)); + Other -> reverse(Other) + end. + +strip("BRA"++R) -> "BRA"++strip(R); +strip([$v,$b,$u,$N,N|R]) when N > 47, N < 58 ->R; +strip([$v,$i,$u,$N,N|R]) when N > 47, N < 58 ->R; +strip([$v,$s,$u,$N,N|R]) when N > 47, N < 58 ->R; +strip([$v,$b,$N,N|R]) when N > 47, N < 58 -> R; +strip([$v,$i,$N,N|R]) when N > 47, N < 58 -> R; +strip([$v,$s,$N,N|R]) when N > 47, N < 58 -> R; +strip([$v,$d,$N,N|R]) when N > 47, N < 58 -> R; +strip([$v,$f,$N,N|R]) when N > 47, N < 58 -> R; +strip([$b,$u,$N,N|R]) when N > 47, N < 58 -> R; + +strip([$v,$b,$u,N|R]) when N > 47, N < 58 ->R; +strip([$v,$i,$u,N|R]) when N > 47, N < 58 ->R; +strip([$v,$s,$u,N|R]) when N > 47, N < 58 ->R; +strip([$v,$b,N|R]) when N > 47, N < 58 -> R; +strip([$v,$i,N|R]) when N > 47, N < 58 -> R; +strip([$v,$s,N|R]) when N > 47, N < 58 -> R; +strip([$v,$d,N|R]) when N > 47, N < 58 -> R; +strip([$v,$f,N|R]) when N > 47, N < 58 -> R; + +strip([$b,$u,N|R]) when N > 47, N < 58 ->R; +strip([$i,$u,N|R]) when N > 47, N < 58 ->R; +strip([$s,$u,N|R]) when N > 47, N < 58 ->R; +strip([$b,N|R]) when N > 47, N < 58 -> R; +strip([$i,N|R]) when N > 47, N < 58 -> R; +strip([$s,N|R]) when N > 47, N < 58 -> R; +strip([$d,N|R]) when N > 47, N < 58 -> R; +strip([$f,N|R]) when N > 47, N < 58 -> R; + +strip([$v,$b,$u|R]) -> R; +strip([$v,$i,$u|R]) -> R; +strip([$v,$s,$u|R]) -> R; +strip([$v,$b|R]) -> R; +strip([$v,$i|R]) -> R; +strip([$v,$s|R]) -> R; +strip([$v,$d|R]) -> R; +strip([$v,$f|R]) -> R; + +strip(R = "delban" ++ _) -> R; +strip([$d,$e|R]) -> [$e|R]; +strip([$f,$e|R]) -> [$e|R]; +strip([$i,$e|R]) -> [$e|R]; +strip([$d,$x|R]) -> [$x|R]; +strip([$f,$x|R]) -> [$x|R]; +strip([$d,$d|R]) -> [$d|R]; +strip([$f,$d|R]) -> [$d|R]; +strip([$i,$l|R]) -> [$l|R]; +strip([$f,$l|R]) -> [$l|R]; +strip([$i,$r|R]) -> [$r|R]; +strip([$f,$r|R]) -> [$r|R]; +strip([$i,$g|R]) -> [$g|R]; +strip([$f,$g|R]) -> [$g|R]; +strip([$i,$n|R]) -> [$n|R]; +strip([$f,$n|R]) -> [$n|R]; +strip([$d,$n|R]) -> [$n|R]; + +strip([$v,R]) -> R; +strip([N|R]) when N > 47, N < 58 -> R; +strip([_|R="tceRlg"]) -> R; +strip([_|R="thgiLlg"]) -> R; +strip(R) -> R. + +strip2([$b,$u|R]) -> R; +strip2([$i,$u|R]) -> R; +strip2([$s,$u|R]) -> R; +strip2([$b|R]) -> R; +strip2([$i|R]) -> R; +strip2([$s|R]) -> R; +strip2([$d|R]) -> R; +strip2([$f|R]) -> R; +strip2(R) -> R. + +gen_debug(GL, GLU) -> + open_write("../src/gen/gl_debug.hrl"), + erl_copyright(), + w("%% This file is generated DO NOT EDIT~n~n", []), + w("gldebug_table() -> ~n[~n", []), + [printd(F,gl) || F <- GL], + [printd(F,glu) || F <- GLU], + w(" {-1, {mod, func, -1}}~n",[]), + w("].~n~n", []), + close(). + +printd([F|R],Mod) when is_list(F) -> + printd(F,Mod), + printd(R,Mod); +printd([],_) -> ok; +printd(F,Mod) -> + case get(F) of + #func{alt={vector,_VecPos,_Vec}} -> ok; + #func{where=erl} -> ok; + #func{id=Id, name=Method} -> + w(" {~p, {~s, ~s, 0}},~n", [Id, Mod, erl_func_name(Method)]); + _Other -> + io:format("F= ~p => ~p~n", [F, _Other]) + end. diff --git a/lib/wx/api_gen/gl_xml/.gitignore b/lib/wx/api_gen/gl_xml/.gitignore new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/lib/wx/api_gen/gl_xml/.gitignore diff --git a/lib/wx/api_gen/glapi.conf b/lib/wx/api_gen/glapi.conf new file mode 100644 index 0000000000..f9ed7a1065 --- /dev/null +++ b/lib/wx/api_gen/glapi.conf @@ -0,0 +1,333 @@ +%% -*- erlang -*- +% general options + +{skip, %% Skip these functions + [ + %%% GLU + "glu", %% The ones we want is specified in keep + "gluQuad", + "gluBegin", + "gluEnd", + "gluNew", + "gluDelete", +%% "gluTess", +%% "gluGetNurbs", +%% "gluGetTess", + + %%% GL + "glProgramCallbackMESA", + "glGetProgramRegisterfvMESA", + "glGetPointerv", + "glGetBufferPointerv", + "glGetVertexAttribPointerv", + "glGetSeparableFilter", + "glMultiDrawElements", + "glMapBuffer", + "glUnmapBuffer", + "glEdgeFlagPointerEXT", + "glWeightPointerARB", + "glMatrixIndexPointerARB", + "glPixelTransformParameter", + %% OpengGL 3.0 + %"glGetTransformFeedbackVarying", %% Jobbiga + %"glTransformFeedbackVaryings", + + %% EXT + %% By default skip these extensions + "SGIX","SGIS","NV","ATI","AMD","SUN","SUNX","GREMEDY", + "HP","IBM","INTEL","APPLE","3DFX","PGI","EXT"]}. + +%% Exceptions to the above +{keep, + [ + %% GL_EXT_framebuffer_object + "glIsRenderbufferEXT", + "glBindRenderbufferEXT", + "glDeleteRenderbuffersEXT", + "glGenRenderbuffersEXT", + "glRenderbufferStorageEXT", + "glGetRenderbufferParameterivEXT", + "glIsFramebufferEXT", + "glBindFramebufferEXT", + "glDeleteFramebuffersEXT", + "glGenFramebuffersEXT", + "glCheckFramebufferStatusEXT", + "glFramebufferTexture1DEXT", + "glFramebufferTexture2DEXT", + "glFramebufferTexture3DEXT", + "glFramebufferRenderbufferEXT", + "glGetFramebufferAttachmentParameterivEXT", + "glGenerateMipmapEXT", + %% GL_ATI_separate_stencil + "glStencilOpSeparateATI", + "glStencilFuncSeparateATI", + %% GL_EXT_depth_bounds_test + "glDepthBoundsEXT", + %% GL_EXT_blend_equation_separate + "glBlendEquationSeparateEXT", + %% GL_EXT_stencil_clear_tag + "glStencilClearTagEXT", + %% GL_EXT_framebuffer_blit + "glBlitFramebufferEXT", + %% GL_EXT_framebuffer_multisample + "glRenderbufferStorageMultisampleEXT", + + "gluBuild", % mipmaps* + "gluCheckExtension", "gluErrorString", "gluGetString", + "gluLookAt", "gluOrtho2D", "gluPerspective", "gluPickMatrix", + "gluScaleImage", + + "gluNewQuadric", "gluDeleteQuadric", + "gluQuadricTexture", "gluQuadricOrientation", "gluQuadricNormals", "gluQuadricDrawStyle", + "gluDisk", "gluCylinder", "gluPartialDisk", "gluSphere", + + "gluProject", "gluUnProject" + ]}. + +{vector, [{"glMultiTexCoord",1}, {"glConvolutionParameter",2},{"glVertexAttrib",1}, {"glVertexAttribI",1}]}. + +%% function specific information + +{"glBitmap", {"bitmap", {base,idx_binary}}}. +{"glPolygonStipple", {"mask", binary}}. +{"glGetPolygonStipple", [{"mask", [{binary, 128},out, {single,true}]}]}. +{"glClipPlane", {"equation", {single,{tuple,4}}}}. +{"glGetClipPlane", {"equation", {single,{tuple,4}}}}. +{"glLoadMatrix", {"m", {single,{tuple,matrix}}}}. +{"glMultMatrix", {"m", {single,{tuple,matrix}}}}. +{"glCallLists", [{"n", {c_only, {length, "lists"}}}, + {"type", {c_only, {constant, "GL_UNSIGNED_INT"}}}, + {"lists", [{single,list},{type,"GLuint"}, {base,int}]}]}. +{"glLight", {"params", {single,{tuple,undefined}}}}. +{"glGetLight", {"params", {single, {tuple, 4}}}}. +{"glMaterial", {"params", {single,{tuple,undefined}}}}. +{"glGetMaterial", {"params", {single, {tuple, 4}}}}. +{"glPixelMap", {"values", binary}}. +{"glGetPixelMap", {"values", [{base,memory}, in]}}. +{"glTexGen", {"params",{single,{tuple,undefined}}}}. +{"glGetTexGen", {"params",{single,{tuple,4}}}}. +{"glTexEnv", {"params",{single,{tuple,undefined}}}}. +{"glGetTexEnv", {"params",{single,{tuple,4}}}}. +{"glTexParameter", {"params",{single,{tuple,undefined}}}}. +{"glGetTexParameter", {"params",{single,{tuple,4}}}}. +{"glGetTexLevelParameter", {"params", {single,{tuple,1}}}}. +{"glGenTextures", [{"textures", {single,{list,"n","n"}}}]}. +{"glDeleteTextures", [{"n", {c_only, {length, "textures"}}}, + {"textures", [{single,list}]}]}. +{"glPrioritizeTextures", [{"n", {c_only, {length, "textures"}}}, + {"textures", [{single,list}]}, + {"priorities", [{single,list}]}]}. +{"glAreTexturesResident", [{"n", {c_only,{length,"textures"}}}, + {"textures", [{single,list}]}, + {"residences", [{single,{list,"texturesLen","texturesLen"}}]}]}. +{"glMap", {"points", binary}}. +{"glGetMap", {"v", [{base,memory},in]}}. +{"glFog", {"params", {single,{tuple,undefined}}}}. +{"glColorTableParameter", {"params",{single,{tuple,4}}}}. +{"glGetColorTable", {"table", [{base,memory},in]}}. +{"glGetColorTableParameter", {"params", {single,{tuple,4}}}}. +{"glGetHistogram", {"values", [{base,memory}, in]}}. +{"glGetHistogramParameter", {"params", {single,{tuple,1}}}}. +{"glGetMinmax", {"values", [{base,memory}, in]}}. +{"glGetMinmaxParameter", {"params", {single,{tuple,1}}}}. +{"glGetConvolutionFilter", {"image", [{base,memory}, in]}}. +{"glConvolutionParameter", {"params", {single,{tuple,undefined}} }}. +{"glGetConvolutionParameter", {"params", {single,{tuple,4}}}}. + +{"glRect", [{"v1", {single,{tuple,2}}},{"v2", {single,{tuple,2}}}]}. + +{"glGetString", {"result", {single,{list,null}}}}. +{"glGetBooleanv", {"params", {single,{list,16}}}}. +{"glGetDoublev", {"params", {single,{list,16}}}}. +{"glGetFloatv", {"params", {single,{list,16}}}}. +{"glGetIntegerv", {"params", {single,{list,16}}}}. + +{"glFeedbackBuffer", {"buffer", [{base,memory}, in]}}. +{"glSelectBuffer", {"buffer", [{base,memory}, in]}}. +{"glReadPixels", {"pixels", [{base,memory}, in]}}. +{"glGetTexImage", {"pixels", [{base,memory}, in]}}. +{"glGetCompressedTexImage", {"img", [{base,memory}, in]}}. + +{"glLoadTransposeMatrix", {"m", {single,{tuple,matrix}}}}. +{"glMultTransposeMatrix", {"m",{single,{tuple,matrix}}}}. + +{"glMultiDrawArrays", [{"first", [in,{single,list}]}, + {"count", [in,{single,list}]}, + {"primcount", {c_only, {length,"first"}}}]}. + +{"glGenQueries", {"ids", {single,{list, "n", "n"}}}}. +{"glGetQueryiv", {"params", {single, true}}}. +{"glGetQueryObject", {"params", {single, true}}}. + +{"glPointParameter", {"params", {single,{tuple,undefined}} }}. +{"glDeleteQueries", [{"n",{c_only,{length,"ids"}}},{"ids",[{single,list}]}]}. +{"glGenBuffers", {"buffers",[{single,{list,"n","n"}}]}}. +{"glGetBufferSubData", {"data", [{base,memory}, in]}}. +{"glGetBufferParameteriv", {"params", {single,true}}}. +{"glDeleteBuffers", [{"n",{c_only,{length,"buffers"}}},{"buffers",[{single,list}]}]}. +{"glDrawBuffers", [{"n",{c_only,{length,"bufs"}}},{"bufs",[{single,list}]}]}. + +{"glShaderSource", [{"length", {c_only,{constant,"NULL"}}}, + {"count", {c_only,{length,"string"}}}, + {"string", {single,list}}]}. + +{"glGetActiveAttribARB", [{"length",[skip,{single, true}]}, + {"size", {single, true}}, + {"type", {single, true}}, + {"name", {single, {list,"maxLength","length"}}} + ]}. + +{"glGetActiveAttrib", [{"length",[skip,{single, true}]}, + {"size", {single, true}}, + {"type", {single, true}}, + {"name", {single, {list,"bufSize","length"}}} + ]}. + +{"glGetActiveUniformARB", [{"length",[skip,{single, true}]}, + {"size", {single, true}}, + {"type", {single, true}}, + {"name", {single, {list,"maxLength","length"}}} + ]}. +{"glGetActiveUniform", [{"length",[skip,{single, true}]}, + {"size", {single, true}}, + {"type", {single, true}}, + {"name", {single, {list,"bufSize","length"}}} + ]}. + +{"glGetAttachedShaders", [{"count", [skip,{single,true}]}, + {"obj", {single, {list,"maxCount","count"}}} + ]}. + +{"glGetProgramiv", {"params", {single,true}}}. + +{"glGetProgramInfoLog", [{"length", [skip,{single,true}]}, + {"infoLog", {single, {list,"bufSize","length"}}} + ]}. +{"glGetShaderiv", {"params", {single,true}}}. +{"glGetShaderInfoLog", [{"length", [skip,{single,true}]}, + {"infoLog", {single, {list,"bufSize","length"}}} + ]}. + +{"glGetShaderSourceARB", [{"length", [skip,{single,true}]}, + {"source", {single, {list,"maxLength","length"}}} + ]}. +{"glGetShaderSource", [{"length", [skip,{single,true}]}, + {"source", {single, {list,"bufSize","length"}}} + ]}. + + +{"glGetUniform", {"params", {single,{tuple,16}}}}. +{"glGetVertexAttrib", {"params", {single,{tuple,4}}}}. + +{"glUniform1", [{"count",{c_only,{length,"value"}}}, {"value", [{single,list}]}]}. +{"glUniform2", [{"count",{c_only,{length,"value"}}}, {"value", [{single,{tuple_list,2}}]}]}. +{"glUniform3", [{"count",{c_only,{length,"value"}}}, {"value", [{single,{tuple_list,3}}]}]}. +{"glUniform4", [{"count",{c_only,{length,"value"}}}, {"value", [{single,{tuple_list,4}}]}]}. +{"glUniformMatrix2fv", [{"count",{c_only,{length,"value"}}},{"value", [{single,{tuple_list,4}}]}]}. +{"glUniformMatrix3fv", [{"count",{c_only,{length,"value"}}},{"value", [{single,{tuple_list,9}}]}]}. +{"glUniformMatrix4fv", [{"count",{c_only,{length,"value"}}},{"value", [{single,{tuple_list,16}}]}]}. +{"glUniformMatrix2x3fv", [{"count",{c_only,{length,"value"}}},{"value", [{single,{tuple_list,6}}]}]}. +{"glUniformMatrix3x2fv", [{"count",{c_only,{length,"value"}}},{"value", [{single,{tuple_list,6}}]}]}. +{"glUniformMatrix2x4fv", [{"count",{c_only,{length,"value"}}},{"value", [{single,{tuple_list,8}}]}]}. +{"glUniformMatrix4x2fv", [{"count",{c_only,{length,"value"}}},{"value", [{single,{tuple_list,8}}]}]}. +{"glUniformMatrix3x4fv", [{"count",{c_only,{length,"value"}}},{"value", [{single,{tuple_list,12}}]}]}. +{"glUniformMatrix4x3fv", [{"count",{c_only,{length,"value"}}},{"value", [{single,{tuple_list,12}}]}]}. +{"glVertexAttrib4", {"v", {single, {tuple,4}}}}. + + +{"glWeight", [{"size",{c_only,{length,"weights"}}}, {"weights", {single,list}}]}. +{"glMatrixIndex", [{"size",{c_only,{length,"indices"}}}, {"indices", {single,list}}]}. + + +{"glProgramStringARB", [{"len",{c_only,{constant,"stringLen"}}}, + {"string",[{base,string},{single,true}]}]}. +{"glGetProgramStringARB", {"string", [in,{base,memory}]}}. +{"glGenProgramsARB", {"programs", {single,{list,"n","n"}}}}. +{"glDeleteProgramsARB", [{"n",{c_only,{length,"programs"}}},{"programs",{single,list}}]}. +{"glProgramEnvParameter4", {"params", {single,{tuple,4}}}}. +{"glGetProgramEnvParameter", {"params", {single,{tuple,4}}}}. +{"glProgramLocalParameter", {"params", {single,{tuple,4}}}}. +{"glGetProgramLocalParameter", {"params", {single,{tuple,4}}}}. +{"glGetObjectParameter", {"params", {single,true}}}. +{"glGetInfoLogARB", [{"length", [skip,{single,true}]}, + {"infoLog", {single, {list,"maxLength","length"}}} + ]}. +{"glGetAttachedObjectsARB", [{"count", [skip,{single,true}]}, + {"obj", {single, {list,"maxCount","count"}}} + ]}. + +{"glGenRenderbuffersEXT", {"renderbuffers", {single,{list,"n","n"}}}}. +{"glDeleteRenderbuffersEXT",[{"n",{c_only,{length,"renderbuffers"}}},{"renderbuffers",{single,list}}]}. +{"glDeleteFramebuffersEXT", [{"n",{c_only,{length,"framebuffers"}}},{"framebuffers",{single,list}}]}. +{"glGetRenderbufferParameterivEXT", {"params", {single,true}}}. + +{"glGetFramebufferAttachmentParameterivEXT", {"params",{single,true}}}. +{"glGenFramebuffersEXT", {"framebuffers",{single,{list,"n","n"}}}}. + +{"gluPickMatrix", {"viewport", [in, {single, {tuple, 4}}]}}. +{"gluProject", [{"model", {single, {tuple, matrix}}}, + {"proj", {single, {tuple, matrix}}}, + {"view", {single, {tuple, 4}}}, + {"winX", [{single,true},out]}, + {"winY", [{single,true},out]}, + {"winZ", [{single,true},out]}]}. +{"gluUnProject", [{"model", {single, {tuple, matrix}}}, + {"proj", {single, {tuple, matrix}}}, + {"view", {single, {tuple, 4}}}, + {"objX",[{single,true},out]}, + {"objY",[{single,true},out]}, + {"objZ",[{single,true},out]}, + {"objW",[{single,true},out]}]}. +{"gluBuild", {"data", [binary]}}. +{"gluScaleImage", [{"dataIn", [in, binary]}, {"dataOut", [in, {base, memory}]}]}. +{"gluCheckExtension", [{"extName", {single, list}}, {"extString", {single, list}}]}. +{"gluErrorString", {"result", {single, {list,null}}}}. +{"gluGetString", {"result", {single, {list,null}}}}. + +{"gluDeleteQuadric", {"quad", in}}. +{"gluQuadric", {"quad", in}}. +{"gluSphere", {"quad", in}}. +{"gluPartialDisk", {"quad", in}}. +{"gluDisk", {"quad", in}}. +{"gluCylinder", {"quad", in}}. + +%% OpenGL 3.0 +{"glGetBooleani_v", {"data", {single,{list,16}}}}. +{"glGetIntegeri_v", {"data", {single,{list,16}}}}. + +{"glTransformFeedbackVaryings", [{"count", {c_only,{length,"varyings"}}}, + {"varyings", [{base,string}, {single,list}]}]}. +{"glGetTransformFeedbackVarying", [{"size", {single, true}},{"type", {single, true}}, + {"length", [skip, {single, true}]}, + {"name", {single, {list,"bufSize","length"}}}]}. + + +{"glGenRenderbuffers", {"renderbuffers", {single,{list,"n","n"}}}}. +{"glGenFramebuffers", {"framebuffers",{single,{list,"n","n"}}}}. +{"glGetRenderbufferParameteriv", {"params", {single,true}}}. +{"glGetFramebufferAttachmentParameteriv", {"params",{single,true}}}. +{"glGenVertexArrays", {"arrays", {single, {list,"n","n"}}}}. +{"glGenRenderbuffers", {"renderbuffers", {single,{list,"n","n"}}}}. +{"glDeleteRenderbuffers",[{"n",{c_only,{length,"renderbuffers"}}}, + {"renderbuffers",{single,list}}]}. +{"glDeleteFramebuffers", [{"n",{c_only,{length,"framebuffers"}}}, + {"framebuffers",{single,list}}]}. +{"glVertexAttribI4", {"v", {single, {tuple,4}}}}. +%% {"glVertexAttribI4", {"v", }}. +%% {"glVertexAttribI4ubv", {"v", }}. +%% {"glVertexAttribI4usv", {"v", }}. +{"glClearBuffer", {"value", {single, {tuple, undefined}}}}. +{"glDeleteVertexArrays", [{"n",{c_only,{length,"arrays"}}},{"arrays", {single, list}}]}. + +{"glGetUniformIndices", [{"uniformCount", {c_only, {length, "uniformNames"}}}, + {"uniformNames", [{base,string}, {single,list}]}, + {"uniformIndices", [out, {single,{list, "uniformNamesLen", "uniformNamesLen"}}]}]}. +{"glGetActiveUniformsiv", [{"uniformCount", {c_only, {length, "uniformIndices"}}}, + {"uniformIndices", {single,list}}, + {"params", [out, {single, {list, "uniformIndicesLen", "uniformIndicesLen"}}]}]}. + +{"glGetActiveUniformName", [{"length",[skip,{single, true}]}, + {"uniformName", {single, {list,"bufSize","length"}}}]}. +{"glGetActiveUniformBlockName", [{"length",[skip,{single, true}]}, + {"uniformBlockName", {single, {list,"bufSize","length"}}}]}. +{"glGetActiveUniformBlockiv", {"params", [in, {base,memory}]}}. diff --git a/lib/wx/api_gen/wx_doxygen.conf b/lib/wx/api_gen/wx_doxygen.conf new file mode 100644 index 0000000000..1fc57486e6 --- /dev/null +++ b/lib/wx/api_gen/wx_doxygen.conf @@ -0,0 +1,299 @@ +# Doxyfile 1.4.3 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = wxe +PROJECT_NUMBER = 0.1 +OUTPUT_DIRECTORY = ./ +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = YES +EXTRACT_ANON_NSPACES = YES +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = YES +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = NO +INLINE_INFO = NO +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = NO +GENERATE_TESTLIST = NO +GENERATE_BUGLIST = NO +GENERATE_DEPRECATEDLIST= NO +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = NO +WARN_IF_UNDOCUMENTED = NO +WARN_IF_DOC_ERROR = NO +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = @WXGTK_DIR@/wx/ wx_extra/ +#FILE_PATTERNS = *.h +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = mac/* mgl/* msw/* os2/* x11/* gtk1/* cocoa/* motif/* msdos/* palmos/* private/* +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +USE_HTAGS = NO +VERBATIM_HEADERS = NO +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = NO +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = YES +XML_OUTPUT = ./wx_xml/ +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = NO +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = \ + wxUSE_MENUS=1 \ + wxUSE_TOOLBAR=1 \ + wxUSE_CONTROLS=1 \ + wxUSE_BUTTON=1 \ + wxUSE_STATBOX=1 \ + wxUSE_BOOKCTRL=1 \ + wxUSE_CHOICE=1 \ + wxUSE_STATUSBAR=1 \ + wxUSE_TEXTCTRL=1 \ + wxUSE_GUI=1 \ + wxUSE_GRID=1 \ + wxUSE_TOGGLE_BTN=1 \ + wxUSE_MSGDLG=1 \ + wxUSE_FILEDLG=1 \ + wxUSE_XRC=1 \ + wxUSE_STATTEXT=1 \ + wxUSE_STATLINE=1 \ + wxUSE_LISTCTRL=1 \ + wxUSE_ACCEL=1 \ + wxUSE_CARET=1 \ + wxUSE_CONSTRAINTS=1 \ + wxUSE_TOOLTIPS=1 \ + wxUSE_DRAG_AND_DROP=1 \ + wxUSE_HELP=1 \ + wxUSE_IMAGE=1 \ + wxUSE_VALIDATORS=1 \ + wxUSE_UNICODE=1 \ + wxUSE_CALENDARCTRL=1 \ + wxUSE_DATETIME=1 \ + wxUSE_COMBOBOX=1 \ + wxUSE_GAUGE=1 \ + wxUSE_LISTBOX=1 \ + wxUSE_BMPBUTTON=1 \ + wxUSE_CHECKBOX=1 \ + wxUSE_TREECTRL=1 \ + wxUSE_LISTCTRL=1 \ + wxUSE_BOOKCTRL=1 \ + wxUSE_NOTEBOOK=1 \ + wxUSE_CHOICEBOOK=1 \ + wxUSE_TOOLBOOK=1 \ + wxUSE_LISTBOOK=1 \ + wxUSE_TREEBOOK=1 \ + wxUSE_SPINBTN=1 \ + wxUSE_FINDREPLDLG=1 \ + wxUSE_TEXTDLG=1 \ + wxUSE_FONTDLG=1 \ + wxUSE_DIRDLG=1 \ + wxUSE_PRINTING_ARCHITECTURE=1 \ + wxUSE_HTML=1 \ + wxUSE_POSTSCRIPT=1 \ + wxUSE_PROGRESSDLG=1 \ + wxUSE_RADIOBOX=1 \ + wxUSE_MINIFRAME=1 \ + wxUSE_PALETTE=1 \ + wxUSE_SASH=1 \ + wxTopLevelWindowNative=1 \ + wxUSE_GLCANVAS=1 \ + wxUSE_GRAPHICS_CONTEXT=1 \ + wxUSE_AUI=1 \ + wxUSE_MDI_ARCHITECTURE=1 \ + wxUSE_FILEPICKERCTRL=1 \ + wxUSE_DIRPICKERCTRL=1 \ + wxUSE_FONTPICKERCTRL=1 \ + wxUSE_DATEPICKCTRL=1 \ + wxUSE_COLOURPICKERCTRL=1 \ + wxUSE_DATAOBJ=1 \ + wxUSE_SLIDER=1 \ + wxUSE_CLIPBOARD=1 \ + wxABI_VERSION=20809 \ + __WXGTK24__=1 \ + __WXGTK__=1 \ + WXDLLEXPORT="" + +# WXWIN_COMPATIBILITY_2_6=1 \ + +EXPAND_AS_DEFINED = YES +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO + diff --git a/lib/wx/api_gen/wx_extra/bugs.h b/lib/wx/api_gen/wx_extra/bugs.h new file mode 100644 index 0000000000..b8f3dfcb00 --- /dev/null +++ b/lib/wx/api_gen/wx_extra/bugs.h @@ -0,0 +1,36 @@ + +// I have added this doxygen seems to get lost in some macros +// in sashwin.h + +enum wxSashDragStatus + { + wxSASH_STATUS_OK, + wxSASH_STATUS_OUT_OF_RANGE + }; + +// Macro needed in erlang +class WXDLLIMPEXP_XRC wxXmlResource : public wxObject +{ + public: + wxObject xrcctrl(wxWindow *Window, wxString Name, wxString Type); +}; + +// The generater needs constructors +class WXDLLIMPEXP_ADV wxGridCellBoolRenderer : public wxGridCellRenderer +{ + public: + wxGridCellBoolRenderer(); +}; + +class WXDLLIMPEXP_ADV wxGridCellStringRenderer : public wxGridCellRenderer +{ + public: + wxGridCellStringRenderer(); +}; + +class WXDLLIMPEXP_ADV wxGridCellNumberRenderer : public wxGridCellStringRenderer +{ + public: + wxGridCellNumberRenderer(); +}; + diff --git a/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src b/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src new file mode 100644 index 0000000000..4e492db045 --- /dev/null +++ b/lib/wx/api_gen/wx_extra/wxEvtHandler.c_src @@ -0,0 +1,66 @@ +case 98: { // wxeEvtListener::wxeEvtListener + wxeEvtListener *Result = new wxeEvtListener(Ecmd.port); + rt.addRef(getRef((void *)Result,memenv), "wxeEvtListener"); + break; +} +case 99: { // wxeEvtListener::destroy + wxObject *This = (wxObject *) getPtr(bp,memenv); + rt.addAtom("ok"); + delete This; + break; +} + +case 100: { // wxEvtHandler::Connect + wxeEvtListener *Listener = (wxeEvtListener *) getPtr(bp,memenv); bp += 4; + wxEvtHandler *This = (wxEvtHandler *) getPtr(bp, memenv); bp += 4; + int * winid = (int *) bp; bp += 4; + int * lastId = (int *) bp; bp += 4; + int * skip = (int *) bp; bp += 4; + int * haveUserData = (int *) bp; bp += 4; + wxeErlTerm * userData = NULL; + int * fun_cb = (int *) bp; bp += 4; + int * eventTypeLen = (int *) bp; bp += 4; + int * class_nameLen = (int *) bp; bp += 4; + + if(*haveUserData) { + userData = new wxeErlTerm(Ecmd.bin[0]); + } + + int eventType = wxeEventTypeFromAtom(bp); bp += *eventTypeLen; + char *class_name = bp; bp+= *class_nameLen; + if(eventType > 0 ) { + wxeCallbackData * Evt_cb = new wxeCallbackData(Ecmd.caller,(void *) This, + class_name,*fun_cb, + *skip, userData); + This->Connect((int) *winid,(int) *lastId,eventType, + (wxObjectEventFunction)(wxEventFunction) &wxeEvtListener::forward, + Evt_cb, Listener); + rt.addAtom("ok"); + } else { + rt.addAtom("badarg"); + rt.addAtom("event_type"); + rt.addTupleCount(2); + } + break; +} +case 101: { // wxEvtHandler::Disconnect + wxeEvtListener *Listener = (wxeEvtListener *) getPtr(bp,memenv); bp += 4; + wxEvtHandler *This = (wxEvtHandler *) getPtr(bp, memenv); bp += 4; + int * winid = (int *) bp; bp += 4; + int * lastId = (int *) bp; bp += 4; + int * eventTypeLen = (int *) bp; bp += 4; + + int eventType = wxeEventTypeFromAtom(bp); bp += *eventTypeLen; + if(eventType > 0) { + bool Result = This->Disconnect((int) *winid,(int) *lastId,eventType, + (wxObjectEventFunction)(wxEventFunction) + &wxeEvtListener::forward, + NULL, Listener); + rt.addBool(Result); + } else { + rt.addAtom("badarg"); + rt.addAtom("event_type"); + rt.addTupleCount(2); + } + break; +} diff --git a/lib/wx/api_gen/wx_extra/wxEvtHandler.erl b/lib/wx/api_gen/wx_extra/wxEvtHandler.erl new file mode 100644 index 0000000000..c6810eb32c --- /dev/null +++ b/lib/wx/api_gen/wx_extra/wxEvtHandler.erl @@ -0,0 +1,183 @@ +%% This module is actually handwritten see ../api_gen/wx_extra/wxEvtHandler.erl +%% +%% @doc The Event handler. +%% +%% To get events from wxwidgets objects you subscribe to them by +%% calling connect/[2-3]. Events are sent as messages, if no callback +%% was supplied These messages will be {@link wx(). #wx{}} where +%% EventRecord is a record that depends on the {@link +%% wxEventType(). event type}. The records are defined in: +%% wx/include/wx.hrl. +%% +%% If a callback was supplied to connect, the callback will be invoked +%% (in another process) to handle the event. The callback should be of +%% arity 2. fun(EventRecord::wx(), EventObject::wxObject()). +%% +%% Beware that the callback will be in executed in new process each time. +%% +%% <a href="http://www.wxwidgets.org/manuals/stable/wx_wxevthandler.html"> +%% The orginal documentation</a>. +%% +%% @headerfile "../../include/wx.hrl" +%% +%%@type wxEvtHandler(). An object reference + +-module(wxEvtHandler). +-include("wxe.hrl"). +-include("../include/wx.hrl"). + +%% API +-export([connect/2, connect/3, disconnect/1, disconnect/2, disconnect/3]). + +%% internal exports +-export([connect_impl/3, disconnect_impl/2, disconnect_impl/3, + new_evt_listener/0, destroy_evt_listener/1, + get_callback/1, replace_fun_with_id/2]). + +-record(evh, {et=null,id=?wxID_ANY,lastId=?wxID_ANY,skip=undefined,userdata=[],cb=0}). + + + +%% @spec (This::wxEvtHandler(), EventType::wxEventType()) -> ok +%% @doc Equivalent to {@link connect/3. connect(This, EventType, [])} + +connect(This, EventType) -> + connect(This, EventType, []). + +%% @spec (This::wxEvtHandler(), EventType::wxEventType(), [Options]) -> ok +%% @doc This function subscribes the to events of EventType, +%% in the range id, lastId. The events will be received as messages +%% if no callback is supplied. +%% +%% Options: +%% {id, integer()}, The identifier (or first of the identifier range) to be +%% associated with this event handler. +%% Default ?wxID_ANY +%% {lastId, integer()}, The second part of the identifier range. +%% If used 'id' must be set as the starting identifier range. +%% Default ?wxID_ANY +%% {skip, boolean()}, If skip is true further event_handlers will be called. +%% This is not used if the 'callback' option is used. +%% Default false. +%% {callback, function()} Use a callback fun(EventRecord::wx(), EventObject::wxObject()) +%% to process the event. Default not specfied i.e. a message will +%% be delivered to the process calling this function. +%% {userData, term()} An erlang term that will be sent with the event. Default: []. +connect(This=#wx_ref{type=ThisT}, EventType, Options) -> + EvH = parse_opts(Options, #evh{et=EventType}), + ?CLASS(ThisT,wxEvtHandler), + case wxe_util:connect_cb(This, EvH) of + ok -> ok; + {badarg, event_type} -> + erlang:error({badarg,EventType}) + end. + +parse_opts([{callback,Fun}|R], Opts) when is_function(Fun) -> + %% Check Fun Arity? + parse_opts(R, Opts#evh{cb=Fun}); +parse_opts([callback|R], Opts) -> + parse_opts(R, Opts#evh{cb=1}); +parse_opts([{userData, UserData}|R],Opts) -> + parse_opts(R, Opts#evh{userdata=UserData}); +parse_opts([{skip, Skip}|R],Opts) when is_boolean(Skip) -> + parse_opts(R, Opts#evh{skip=Skip}); +parse_opts([{id, Id}|R],Opts) when is_integer(Id) -> + parse_opts(R, Opts#evh{id=Id}); +parse_opts([{lastId, Id}|R],Opts) when is_integer(Id) -> + parse_opts(R, Opts#evh{lastId=Id}); +parse_opts([_BadArg|R], Opts) -> + parse_opts(R, Opts); +parse_opts([], Opts = #evh{id=Id,lastId=Lid,skip=Skip, cb=CB}) -> + if + Skip =/= undefined andalso CB =/= 0 -> + erlang:error({badarg, {combined, skip, callback}}); + Lid =/= ?wxID_ANY andalso Id =:= ?wxID_ANY -> + erlang:error({badarg, no_start_identifier_range}); + Skip =:= undefined -> %% Default + Opts#evh{skip=false}; + true -> + Opts + end. + +%% @spec (This::wxEvtHandler()) -> true | false +%% @doc Equivalent to {@link disconnect/3. disconnect(This, null, [])} +%% Can also have an optional callback Fun() as an additional last argument. + +disconnect(This=#wx_ref{type=ThisT,ref=_ThisRef}) -> + ?CLASS(ThisT,wxEvtHandler), + disconnect(This, null, []). + +%% @spec (This::wxEvtHandler(), EventType::wxEventType()) -> true | false +%% @doc Equivalent to {@link disconnect/3. disconnect(This, EventType, [])} +disconnect(This=#wx_ref{type=ThisT,ref=_ThisRef}, EventType) when is_atom(EventType) -> + ?CLASS(ThisT,wxEvtHandler), + disconnect(This, EventType, []). + +%% @spec (This::wxEvtHandler(), EventType::wxEventType(), Opts) -> true | false +%% @doc See <a href="http://www.wxwidgets.org/manuals/stable/wx_wxevthandler.html#wxevthandlerdisconnect">external documentation</a> +%% This function unsubscribes the process or callback fun from the event handler. +%% EventType may be the atom 'null' to match any eventtype. +%% Notice that the options skip and userdata is not used to match the eventhandler. +disconnect(This=#wx_ref{type=ThisT,ref=_ThisRef}, EventType, Opts) -> + ?CLASS(ThisT,wxEvtHandler), + EvH = parse_opts(Opts, #evh{et=EventType}), + case wxe_util:disconnect_cb(This, EvH) of + {badarg, event_type} -> + erlang:error({badarg,EventType}); + Bool -> + Bool + end. + + +%% @hidden +connect_impl(#wx_ref{type=wxeEvtListener,ref=EvtList}, + #wx_ref{type=ThisT,ref=ThisRef}, + #evh{id=Winid, lastId=LastId, et=EventType, + skip=Skip, userdata=Userdata, cb=FunID}) + when is_integer(FunID)-> + EventTypeBin = list_to_binary([atom_to_list(EventType)|[0]]), + ThisTypeBin = list_to_binary([atom_to_list(ThisT)|[0]]), + UD = if Userdata =:= [] -> 0; + true -> + wxe_util:send_bin(term_to_binary(Userdata)), + 1 + end, + wxe_util:call(100, <<EvtList:32/?UI,ThisRef:32/?UI, + Winid:32/?UI,LastId:32/?UI, + (wxe_util:from_bool(Skip)):32/?UI, + UD:32/?UI, + FunID:32/?UI, + (size(EventTypeBin)):32/?UI, + (size(ThisTypeBin)):32/?UI, + %% Note no alignment + EventTypeBin/binary,ThisTypeBin/binary>>). + +%% @hidden +disconnect_impl(Listener, Object) -> + disconnect_impl(Listener, Object, #evh{}). +%% @hidden +disconnect_impl(#wx_ref{type=wxeEvtListener,ref=EvtList}, + #wx_ref{type=_ThisT,ref=ThisRef}, + #evh{id=Winid, lastId=LastId, et=EventType}) -> + EventTypeBin = list_to_binary([atom_to_list(EventType)|[0]]), + wxe_util:call(101, <<EvtList:32/?UI, + ThisRef:32/?UI,Winid:32/?UI,LastId:32/?UI, + (size(EventTypeBin)):32/?UI, + %% Note no alignment + EventTypeBin/binary>>). + +%% @hidden +new_evt_listener() -> + wxe_util:call(98, <<>>). + +%% @hidden +destroy_evt_listener(#wx_ref{type=wxeEvtListener,ref=EvtList}) -> + wxe_util:call(99, <<EvtList:32/?UI>>). + +%% @hidden +get_callback(#evh{cb=Callback}) -> + Callback. + +%% @hidden +replace_fun_with_id(Evh, Id) -> + Evh#evh{cb=Id}. diff --git a/lib/wx/api_gen/wx_extra/wxListCtrl.c_src b/lib/wx/api_gen/wx_extra/wxListCtrl.c_src new file mode 100644 index 0000000000..cd3074e481 --- /dev/null +++ b/lib/wx/api_gen/wx_extra/wxListCtrl.c_src @@ -0,0 +1,24 @@ +<<SortItems +case ~s: { // wxListCtrl::SortItems taylormade + wxListCtrl *This = (wxListCtrl *) getPtr(bp,memenv); bp += 4; + int sortCallback=*(int *) bp; bp += 4; + if(!This) throw wxe_badarg(0); + + callbackInfo* cb = new callbackInfo(); + cb->port = Ecmd.port; + cb->callbackID = sortCallback; + bool Result = This->SortItems(wxEListCtrlCompare, (long)cb); + delete cb; + + /* Destroy the callback, see wxEPrintout::clear_cb */ + wxeReturn cbrt = wxeReturn(WXE_DRV_PORT, memenv->owner, false); + // NOTE: Remove this later when changing from funs to gen_server + cbrt.addAtom("wx_delete_cb"); + cbrt.addInt(sortCallback); + cbrt.addTupleCount(2); + cbrt.send(); + + rt.addBool(Result); + break; +} +SortItems>> diff --git a/lib/wx/api_gen/wx_extra/wxListCtrl.erl b/lib/wx/api_gen/wx_extra/wxListCtrl.erl new file mode 100644 index 0000000000..e6470182cb --- /dev/null +++ b/lib/wx/api_gen/wx_extra/wxListCtrl.erl @@ -0,0 +1,39 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 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% +%% +<<EXPORT:SortItems sortItems/2 SortItems:EXPORT>> + +<<SortItems +%% @spec (This::wxListCtrl(), SortCallBack::function()) -> boolean() +%% @doc Sort the items in the list control<br /> +%% <pre>SortCalBack(Item1,Item2) -> integer()</pre> +%% <br /> SortCallBack receives the client data associated with two items +%% to compare, and should return 0 if the items are equal, a negative +%% value if the first item is less than the second one and a positive +%% value if the first item is greater than the second one. +%% <br /> NOTE: The callback may not call other processes. +sortItems(#wx_ref{type=ThisT,ref=ThisRef}, SortCallBack) + when is_function(SortCallBack, 2) -> + ?CLASS(ThisT,wxListCtrl), + Sort = fun([Item1,Item2]) -> + Result = SortCallBack(Item1,Item2), + <<Result:32/?UI>> + end, + SortId = wxe_util:get_cbId(Sort), + wxe_util:call(~s, <<ThisRef:32/?UI,SortId:32/?UI>>). +SortItems>> diff --git a/lib/wx/api_gen/wx_extra/wxPrintout.c_src b/lib/wx/api_gen/wx_extra/wxPrintout.c_src new file mode 100644 index 0000000000..c088a95e73 --- /dev/null +++ b/lib/wx/api_gen/wx_extra/wxPrintout.c_src @@ -0,0 +1,30 @@ +<<wxPrintout +case ~s: { // wxPrintout::wxPrintout taylormade + int onPreparePrinting=0,onBeginPrinting=0,onEndPrinting=0,onBeginDocument=0, + onEndDocument=0,hasPage=0,getPageInfo=0; + int * titleLen = (int *) bp; bp += 4; + wxString title = wxString(bp, wxConvUTF8); + bp += *titleLen+((8-((4+ *titleLen) & 7)) & 7); + int onPrintPage=*(int *) bp; bp += 4; + while( * (int*) bp) { + switch (* (int*) bp) { + case 1: {bp += 4; onPreparePrinting = *(int *) bp; bp += 4;} break; + case 2: {bp += 4; onBeginPrinting = *(int *) bp; bp += 4;} break; + case 3: {bp += 4; onEndPrinting = *(int *) bp; bp += 4;} break; + case 4: {bp += 4; onBeginDocument = *(int *) bp; bp += 4;} break; + case 5: {bp += 4; onEndDocument = *(int *) bp; bp += 4;} break; + case 6: {bp += 4; hasPage = *(int *) bp; bp += 4;} break; + case 7: {bp += 4; getPageInfo = *(int *) bp; bp += 4;} break; + } + } + wxEPrintout *Result = new wxEPrintout(title,onPrintPage, + onPreparePrinting, + onBeginPrinting,onEndPrinting, + onBeginDocument,onEndDocument, + hasPage,getPageInfo, Ecmd.port); + + rt.addRef(getRef((void *)Result,memenv), "wxPrintout"); + break; +} +wxPrintout>> + diff --git a/lib/wx/api_gen/wx_extra/wxPrintout.erl b/lib/wx/api_gen/wx_extra/wxPrintout.erl new file mode 100644 index 0000000000..be8f2e2fa5 --- /dev/null +++ b/lib/wx/api_gen/wx_extra/wxPrintout.erl @@ -0,0 +1,102 @@ +%% +%% %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% +%% +<<EXPORT:wxPrintout new/2,new/3 wxPrintout:EXPORT>> + +<<wxPrintout +%% @spec (Title::string(), OnPrintPage::function()) -> wxPrintout:wxPrintout() +%% @doc @equiv new(Title, OnPrintPage, []) +new(Title, OnPrintPage) -> + new(Title, OnPrintPage, []). + +%% @spec (Title::string(), OnPrintPage::function(), [Option]) -> wxPrintout:wxPrintout() +%% Option = {onPreparePrinting, OnPreparePrinting::function()} | +%% {onBeginPrinting, OnBeginPrinting::function()} | +%% {onEndPrinting, OnEndPrinting::function()} | +%% {onBeginDocument, OnBeginDocument::function()} | +%% {onEndDocument, OnEndDocument::function()} | +%% {hasPage, HasPage::function()} | +%% {getPageInfo, GetPageInfo::function()} +%% @doc Creates a wxPrintout object with a callback fun and optionally other callback funs.<br /> +%% <pre>OnPrintPage(This,Page) -> boolean() </pre> +%% <pre>OnPreparePrinting(This) -> term() </pre> +%% <pre>OnBeginPrinting(This) -> term() </pre> +%% <pre>OnEndPrinting(This) -> term() </pre> +%% <pre>OnBeginDocument(This,StartPage,EndPage) -> boolean() </pre> +%% <pre>OnEndDocument(This) -> term() </pre> +%% <pre>HasPage(This,Page)} -> boolean() </pre> +%% <pre>GetPageInfo(This) -> {MinPage:.integer(), MaxPage::integer(), PageFrom::integer(), PageTo::integer()} </pre> +%% The <b>This</b> argument is the wxPrintout object reference to this object +%% <br /> NOTE: The callbacks may not call other processes. +new(Title, OnPrintPage, Opts) when is_list(Title), is_function(OnPrintPage), is_list(Opts) -> + OnPrint = fun([This,Page]) -> + Bool = OnPrintPage(This,Page), + <<(wxe_util:from_bool(Bool)):32/?UI>> + end, + OnPrintPageId = wxe_util:get_cbId(OnPrint), + MOpts = fun({onPreparePrinting, F},Acc) when is_function(F) -> + Fun = fun([This]) -> + F(This), + <<>> + end, + [<<1:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc]; + ({onBeginPrinting, F},Acc) when is_function(F) -> + Fun = fun([This]) -> + F(This), + <<>> + end, + [<<2:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc]; + ({onEndPrinting, F},Acc) when is_function(F) -> + Fun = fun([This]) -> + F(This), + <<>> + end, + [<<3:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc]; + ({onBeginDocument, F},Acc) when is_function(F) -> + Fun = fun([This,S,E]) -> + BegD = F(This,S,E), + <<(wxe_util:from_bool(BegD)):32/?UI>> + end, + [<<4:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc]; + ({onEndDocument, F},Acc) when is_function(F) -> + Fun = fun([This]) -> + F(This), + <<>> + end, + [<<5:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc]; + ({hasPage, F},Acc) when is_function(F) -> + Fun = fun([This,Page]) -> + HasP = F(This,Page), + <<(wxe_util:from_bool(HasP)):32/?UI>> + end, + [<<6:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc]; + ({getPageInfo, F},Acc) when is_function(F) -> + Fun = fun([This]) -> + {Min,Max,PF,PT} = F(This), + <<Min:32/?UI,Max:32/?UI,PF:32/?UI,PT:32/?UI>> + end, + [<<7:32/?UI,(wxe_util:get_cbId(Fun)):32/?UI>>|Acc] + end, + BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Opts)), + Title_UC = unicode:characters_to_binary([Title,0]), + wxe_util:call(~s, << (byte_size(Title_UC)):32/?UI,Title_UC/binary, + 0:(((8- ((4+byte_size(Title_UC)) band 16#7)) band 16#7))/unit:8, + OnPrintPageId:32/?UI, + BinOpt/binary>>). + +wxPrintout>> diff --git a/lib/wx/api_gen/wx_extra/wxXmlResource.c_src b/lib/wx/api_gen/wx_extra/wxXmlResource.c_src new file mode 100644 index 0000000000..152e83fe32 --- /dev/null +++ b/lib/wx/api_gen/wx_extra/wxXmlResource.c_src @@ -0,0 +1,3 @@ +<<xrcctrl +// XRCTRL macro implemented in erlang funcid ~s +xrcctrl>>
\ No newline at end of file diff --git a/lib/wx/api_gen/wx_extra/wxXmlResource.erl b/lib/wx/api_gen/wx_extra/wxXmlResource.erl new file mode 100644 index 0000000000..cd2bea6a1d --- /dev/null +++ b/lib/wx/api_gen/wx_extra/wxXmlResource.erl @@ -0,0 +1,43 @@ + +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 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% +%% +<<EXPORT:xrcctrl xrcctrl/3 xrcctrl:EXPORT>> + +<<xrcctrl +%% @spec (Window::wxWindow:wxWindow(),Name::string(), Type::atom()) -> wx:wxObject() + +%% @doc Looks up a control with Name in a window created with XML +%% resources. You can use it to set/get values from controls. +%% The object is type casted to <b>Type</b>. +%% Example: <br /> +%% Xrc = wxXmlResource:get(), <br /> +%% Dlg = wxDialog:new(), <br /> +%% true = wxXmlResource:loadDialog(Xrc, Dlg, Frame, "controls_dialog"), <br /> +%% LCtrl = xrcctrl(Dlg, "controls_listctrl", wxListCtrl), <br /> +%% wxListCtrl:insertColumn(LCtrl, 0, "Name", [{width, 200}]), <br /> + +xrcctrl(Window = #wx_ref{}, Name, Type) when is_list(Name), is_atom(Type) -> + %% Func Id ~s + ID = wxXmlResource:getXRCID(Name), + Res = wxWindow:findWindow(Window,ID), + wx:typeCast(Res, Type). + +xrcctrl>> + + diff --git a/lib/wx/api_gen/wx_extra/wxe_evth.h b/lib/wx/api_gen/wx_extra/wxe_evth.h new file mode 100644 index 0000000000..9af603b9e2 --- /dev/null +++ b/lib/wx/api_gen/wx_extra/wxe_evth.h @@ -0,0 +1,25 @@ + +// This add some extra functions, special code is in the compiler +// this file is currently not used at all except to get the inherited +// functions in the erlang modules. + + +class wxeEvtHandler : public wxObject +{ + public: + // Dynamic association of a member function handler with the event handler, + // winid and event type + void Connect(int eventType, + int options = -1); + + // Disconnect + + // Convenience function: take just one id + void Disconnect(int eventType, int winid = -1); + + // Even more convenient: without id (same as using id of wxID_ANY) + void Disconnect(int eventType); + + void Disconnect(); + +} diff --git a/lib/wx/api_gen/wx_gen.erl b/lib/wx/api_gen/wx_gen.erl new file mode 100644 index 0000000000..50dd2d6f51 --- /dev/null +++ b/lib/wx/api_gen/wx_gen.erl @@ -0,0 +1,1443 @@ +%% +%% %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% +%% +%% Api wrapper generator + +-module(wx_gen). +-export([code/0,xml/0]). + +-include("wx_gen.hrl"). + +-include_lib("xmerl/include/xmerl.hrl"). + +-import(lists, [foldl/3,foldr/3,reverse/1, keysearch/3, map/2, filter/2]). +-import(proplists, [get_value/2,get_value/3]). + +-compile(export_all). + +code() -> safe(fun gen_code/0,true). +xml() -> safe(fun gen_xml/0,true). + +devcode() -> erase(),safe(fun gen_code/0,false). + +safe(What, QuitOnErr) -> + try + What(), + io:format("Completed succesfully~n~n", []), + QuitOnErr andalso gen_util:halt(0) + catch Err:Reason -> + io:format("Error in ~p ~p~n", [get(current_class),get(current_func)]), + erlang:display({Err,Reason, erlang:get_stacktrace()}), + catch gen_util:close(), + QuitOnErr andalso gen_util:halt(1) + end. + +gen_code() -> + {ok, Defs0} = file:consult("wxapi.conf"), + %% {ok, Defs0} = file:consult("test.conf"), + erase(func_id), + put(class_id, 10), %% Start from 10 using the other as special + Defs1 = init_defs(Defs0), + Defs2 = parse_defs(Defs1, []), + parse_enums([File || {{include, File},_} <- get()]), + Defs = translate_enums(Defs2), + wx_gen_erl:gen(Defs), + wx_gen_cpp:gen(Defs), + ok. + +gen_xml() -> +%% {ok, Defs} = file:consult("wxapi.conf"), + +%% Rel = reverse(tl(reverse(os:cmd("wx-config --release")))), +%% Dir = " /usr/include/wx-" ++ Rel ++ "/wx/", +%% Files0 = [Dir ++ File || {class, File, _, _, _} <- Defs], +%% Files1 = [Dir ++ File || {doxygen, File} <- Defs], +%% ok = file:write_file("wxapi.files", list_to_binary("INPUT = "++Files0++Files1)), + ok. + +-record(hs,{alias,skip,fs,fopt,ev,acc,info}). + +init_defs(List0) -> + List1 = to_lists(List0), + lists:map(fun mangle_info/1, List1). + +mangle_info(E={enum,Type0,SkipStr}) -> + Type = case is_atom(Type0) of true -> atom_to_list(Type0); false -> Type0 end, + put({enum, Type}, #enum{skip=SkipStr,as_atom=false}), %% as_atom=true}), + E; +mangle_info(E={const_skip,List}) -> + put(const_skip, [atom_to_list(M) || M <- List]), + E; +mangle_info(E={not_const,List}) -> + put(not_const, [atom_to_list(M) || M <- List]), + E; +mangle_info(E={gvars,List}) -> + A2L = fun({N,{T,C}}) -> {atom_to_list(N), {T,atom_to_list(C)}}; + ({N,C}) -> {atom_to_list(N), atom_to_list(C)} + end, + put(gvars, map(A2L,List)), + E; +mangle_info({class,CN,P,O,FL}) -> + Alias = get_value(alias,O, []), + Skip = get_value(skip, O, []), + Event = get_value(event,O, false), + Acc = get_value(acc, O, []), + {Fs,Fopts} = foldr(fun(FWO={F,FO},{Fl,Fopt}) when is_list(FO) -> + {[F|Fl],[FWO|Fopt]}; + (F,{Fl,Fopt}) -> + {[F|Fl], Fopt} + end, {[],[]}, FL), + {class,CN,P,#hs{alias=Alias,skip=Skip,fs=Fs,ev=Event,acc=Acc,info=O, + fopt=gb_trees:from_orddict(lists:sort(Fopts))}}. + +to_lists(Defs) -> + map(fun({class,C,P,O,Fs}) -> + {class,atom_to_list(C),atom_to_list(P),to_lists2(O),to_lists2(Fs)}; + (Skip) -> Skip + end, Defs). + +to_lists2(List) -> + map(fun(Skip = {const_skip, _List}) -> Skip; + (Skip = {not_const, _List}) -> Skip; + (Skip = {skip, _List}) -> Skip; + (Skip = {event, _List}) -> Skip; + (Skip = {acc, _List}) -> Skip; + (Skip = {doc, _List}) -> Skip; + (Skip = taylormade) -> Skip; + (Skip = {ifdef,_}) -> Skip; + (Skip = {erl_func, _Name}) -> Skip; + ({alias, AList}) -> {alias, [{atom_to_list(A),atom_to_list(B)} || {A,B} <- AList]}; + (Else) when is_atom(Else) -> atom_to_list(Else); + ({Else,W}) when is_atom(Else) -> {atom_to_list(Else),W}; + ({{Else,W},O}) when is_atom(Else) -> {{atom_to_list(Else),W},O}; + (Else) -> Else + end, List). + +parse_defs([{class,Name,Parent,Info}|Rest], Acc0) -> + {FileName, Type} = + case Parent of + "static" -> {Name ++ "_8h", static}; + _ -> {"class" ++ Name, class} + end, + Tab = ets:new(defs, [bag]), + Defs0 = load_members(FileName, Name, gb_trees:empty(), Tab, Type, Info), + + put(current_class, Name), + Class0 = #class{name=name(Name,Info),parent=Parent, + doc=get_value(doc,Info#hs.info,undefined), + file=FileName,options=Info#hs.info, id=next_id(class_id)}, + ParseClass = fun(Member,{Class,Dfs}) -> + parse_class(Member,Tab,Dfs,Class,Info) + end, + {Class1,Defs} = foldl(ParseClass,{Class0,Defs0},Info#hs.fs), + + Class2 = case Info#hs.ev of + false -> Class1; + Ev -> parse_attr(gb_trees:to_list(Defs), Class1, Ev, Info) + end, + Class = meta_info(Class2), + erase(current_class), + [erase(Del) || {Del = {loaded, _},_} <- get()], + %% ets:delete(Tab), keep it for debugging + parse_defs(Rest, [Class|Acc0]); +parse_defs([_|Rest], Acc) -> + parse_defs(Rest, Acc); +parse_defs([], Acc) -> reverse(Acc). + +meta_info(C=#class{name=CName,methods=Ms0}) -> + Ms = lists:append(Ms0), + HaveConstructor = + lists:keysearch(constructor, #method.method_type, Ms) =/= false, + case lists:keysearch(destructor, #method.method_type, Ms) of + false when HaveConstructor -> + Dest = #method{name="destroy",id=next_id(func_id), + method_type=destructor, params=[this(CName)]}, + C#class{methods = [[Dest]|Ms0]}; + false -> + C#class{abstract = true}; + _ -> + C + end. + +parse_class(Member0,Tab,Defs0,Class = #class{name=CName},Opts) -> + {Member,NoArgs} = case Member0 of + {_, _} -> Member0; + _ -> {Member0,all} + end, + case ets:lookup(Tab, Member) of + [] -> + case Member of + [$~|_] -> ignore; + _ -> + ?warning("Skipped Member ~p in ~p (not found in ~p)~n", + [Member,CName,Tab]) + end, + {Class,Defs0}; + Ms -> + case select_member(Ms, Class, Defs0, Opts) of + {[],Defs} -> + ?warning("Skipped Member ~p in ~p (not found in base)~n", + [Member,CName]), + {Class,Defs}; + {Selected,Defs} -> + Parsed = parse_members(Member,Selected,Defs,CName,Opts), + {add_method(Parsed,NoArgs,Class,Opts), Defs} + end + end. + +parse_members(MemberName, Members, Defs, Class, Opts) -> + ParseAll = + fun(Member,Acc) -> + try + case gb_trees:lookup(Member, Defs) of + {value,#xmlElement{name=memberdef,attributes=Attrs, + content=Data}} -> + MType = case keysearch(static,#xmlAttribute.name,Attrs) of + {value, #xmlAttribute{value = "yes"}} -> + static; + _ -> + member + end, + Virtual = + case keysearch(virt,#xmlAttribute.name,Attrs) of + {value, #xmlAttribute{value = "virtual"}} -> + true; + {value, #xmlAttribute{value = "non-virtual"}} -> + false; + _ -> + undefined + end, + [parse_member(Data,MType,Virtual,Opts)|Acc]; + none -> + Acc; + _Hmm -> + Acc + end + catch throw:skip_member -> + Acc + end + end, + case foldl(ParseAll,[],Members) of + [] -> + ?warning("Skipped ~p No public def found in ~p ~n", + [MemberName,Class]), + io:format("~p ~p~n",[MemberName, Members]), + []; + Res -> + Res + end. + + +parse_attr(Defs, Class, Ev, Info = #hs{acc=AccList0}) -> +% io:format("Parsing Class ~p~n", [Class#class.name]), + {Attrs, AccList} = parse_attr1(Defs, AccList0, Info, []), + case AccList of + [] -> + Class#class{attributes=Attrs, event=Ev}; + _ -> + Inherited = [{inherited, Inherit} || Inherit <- AccList], + Class#class{attributes=Attrs++Inherited, event=Ev} + end. + +parse_attr1([{{attr,_}, #xmlElement{content=C, attributes=Attrs}}|R], AttrList0, Opts, Res) -> + Parse = fun(Con, Ac) -> parse_param(Con, Opts, Ac) end, + Param0 = foldl(Parse, #param{}, drop_empty(C)), + case keysearch(prot, #xmlAttribute.name, Attrs) of + {value, #xmlAttribute{value = "public"}} -> + {Acc,AttrList} = attr_acc(Param0, AttrList0), + parse_attr1(R,AttrList,Opts, + [Param0#param{in=false,prot=public,acc=Acc}|Res]); + {value, #xmlAttribute{value = "protected"}} -> + {Acc,AttrList} = attr_acc(Param0, AttrList0), + parse_attr1(R,AttrList,Opts, + [Param0#param{in=false,prot=protected,acc=Acc}|Res]); + {value, #xmlAttribute{value = "private"}} -> + {Acc,AttrList} = attr_acc(Param0, AttrList0), + parse_attr1(R,AttrList,Opts, + [Param0#param{in=false,prot=private,acc=Acc}|Res]) + end; +parse_attr1([{_Id,_}|R],AttrList,Info, Res) -> + parse_attr1(R,AttrList,Info, Res); +parse_attr1([],Left,_, Res) -> + {lists:reverse(Res), Left}. + +attr_acc(#param{name=N}, List) -> + Name = list_to_atom(N), + case get_value(Name, List, undefined) of + undefined -> {undefined, List}; + Val -> {Val, lists:keydelete(Name,1,List)} + end. + +load_members(FileName, Class, Defs, Tab, Type,Opts) -> + File = filename:join(["wx_xml",FileName ++ ".xml"]), + put({loaded, FileName}, true), + case xmerl_scan:file(File, [{space, normalize}]) of + {error, enoent} -> + io:format("Skipped File not found ~p ~n", [File]), + Defs; + {Doc, _} -> + %% io:format("Scanning ~p ~n", [File]), + INCs = xmerl_xpath:string("./compounddef/includes/text()", Doc), + [put({include,reverse(tl(tl(reverse(Inc))))},ref) || + #xmlText{value=Inc} <- INCs], + case Type of + class -> + AM = xmerl_xpath:string("./compounddef/listofallmembers/*", Doc), + foldl(fun(X,Y) -> extract_rmembers(X,Y,Opts) end, Tab, AM); + _ -> + ignore + end, + LMembers0 = xmerl_xpath:string("./compounddef/sectiondef/*", Doc), + foldl(fun(E,Acc) -> extract_lmembers(E,Class,Type,Tab,Opts,Acc) end, Defs, LMembers0) + end. + +extract_lmembers(Entry=#xmlElement{name=memberdef,attributes=Attrs,content=C},Class,Type,Tab,Opts,Acc) -> + case keysearch(kind, #xmlAttribute.name, Attrs) of + {value, #xmlAttribute{value = "function"}} -> + case keysearch(prot, #xmlAttribute.name, Attrs) of + {value, #xmlAttribute{value = "public"}} -> + {value, #xmlAttribute{value = Id}} = + keysearch(id, #xmlAttribute.name, Attrs), + case Type of + static -> + Get = fun(#xmlElement{name=name,content=[#xmlText{value=Name}]},NAcc) -> + [name(string:strip(Name),Opts)|NAcc]; + (_D, NAcc) -> + NAcc + end, + case foldl(Get, [], C) of + [Name] -> + true = ets:insert(Tab,{Name,Id}); + [] -> + ignore + end; + _ -> ignore + end, + case gb_trees:lookup(Id,Acc) of + {value, _Entry} -> gb_trees:update(Id,Entry,Acc); + none -> gb_trees:insert(Id,Entry,Acc) + end; + _ -> + Acc + end; + {value, #xmlAttribute{value = "variable"}} when Type =/= static -> +%% {value, #xmlAttribute{value = Id}} = +%% keysearch(id, #xmlAttribute.name, Attrs), + %% Hopefully wxW have some decent order!! + Id = next_id(attr_id), + gb_trees:insert({attr,Id},Entry,Acc); + {value, #xmlAttribute{value = "enum"}} when Type =/= static -> + extract_enum(Entry,Class, undefined), + Acc; + _ -> Acc + + end. + +extract_rmembers(#xmlElement{name=member,attributes=Attrs,content=C},Tab, Opts) -> + {value,#xmlAttribute{value=Id}} = keysearch(refid, #xmlAttribute.name, Attrs), + Get = fun(#xmlElement{name=name,content=[#xmlText{value=Name}]},Acc) -> + [name(string:strip(Name),Opts)|Acc]; + (_D, Acc) -> + Acc + end, + case foldl(Get, [], C) of + [Name] -> + true = ets:insert(Tab,{Name,Id}); + [] -> + ignore + end, + Tab. + +select_member([{_,ID}], #class{name=Class,file=Orig}, Defs0, Opts) -> + [FileName, _8H|_] = string:tokens(ID, "_"), + case get({loaded, FileName}) =:= undefined + andalso get({loaded, FileName ++ "_" ++ _8H}) =:= undefined of + true -> + true = FileName =/= Orig, % Assert + Defs = load_members(FileName, Class, Defs0, skip, skip, Opts), + {[ID],Defs}; + false -> + {[ID],Defs0} + end; +select_member(Several, #class{name=Class,file=Orig}, Defs0, Opts) -> + MIds = [{string:tokens(MId, "_"),MId} || {_,MId} <- Several], + [StatFile |_ ] = string:tokens(Orig, "_"), + Check = + fun({[FN,_|_],ID}, {T,D}) when FN =:= Orig -> {[ID|T],D}; + ({[FN,"8h"|_],ID}, {T,D}) when FN =:= StatFile -> {[ID|T],D}; + ({[FN,_A|_],ID},{T,D}) -> + InBase = "class" ++ Class ++ "Base" =:= FN, + "wx" ++ ClassName = Class, + InGeneric = "classwxGeneric" ++ ClassName =:= FN, + IsHelper = case re:run(FN, "Helper$") of + {match,_} -> true; + _ -> false + end, + ImplBase = case re:run(FN, "Base$") of + {match,_} -> true; + _ -> + %% Hack for base-base class + FN =:= "classwxItemContainer" + end, + case InBase orelse InGeneric orelse IsHelper orelse ImplBase of + true -> + Defs = case get({loaded, FN}) of + undefined -> + true = FN =/= Orig, % Assert + load_members(FN,Class,D,skip,skip,Opts); + true -> D + end, + {[ID|T], Defs}; + _C -> + %% io:format("DBG ~p ~p ~p ~p ~n",[FN,_A,_C,Class]), + {T,D} + end + end, + foldl(Check,{[],Defs0},MIds). + +parse_member(Data,MType,Virtual,Opts = #hs{fopt=Fopts}) -> + Parse = fun(Con,A) -> parse_member2(Con,Opts,A) end, + Method = #method{name=MName,params=PS0} = + foldl(Parse, #method{method_type=MType, virtual=Virtual}, Data), + %% Skip motif name's if it's last and optional + PS2 = case PS0 of %% Backward order.. + [#param{name="name",def=Def,type=#type{name="wxString"}}|PS1] + when Def =/= none -> + PS1; + _ -> + PS0 + end, + Sz = length(PS2), + PS = map(fun(P=#param{name=PName}) -> + patch_param(MName,{Sz,PName},P,Fopts) + end, PS2), + Alias = find_erl_alias_name(MName,PS,Fopts), + Method#method{params=PS, alias=Alias}. + +find_erl_alias_name(MName,Ps,Fopts) -> + case gb_trees:lookup(MName, Fopts) of + {value, FuncO} when is_list(FuncO) -> + Aliases = lists:foldl(fun({Var, {erl_func, AliasName}}, Acc) -> + [{Var,AliasName}|Acc]; + ({erl_func, AliasName}, Acc) -> + [{all,AliasName}|Acc]; + ({Var, List}, Acc) when is_list(List) -> + case get_value(erl_func,List) of + undefined -> + Acc; + AliasName -> + [{Var,AliasName}|Acc] + end; + (_,Acc) -> Acc + end, [], FuncO), + case Aliases of + [] -> + undefined; + _ -> + Find = fun({all,AliasName},Acc) -> [AliasName|Acc]; + ({Var,AliasName},Acc) -> + case lists:keysearch(Var, #param.name, Ps) of + {value, _} -> [AliasName|Acc]; + _ -> Acc + end + end, + case lists:foldl(Find, [], Aliases) of + [Alias] -> Alias; + [] -> undefined + end + end; + _ -> + undefined + end. + +parse_member2(#xmlElement{name=type, content=C},Opts,M0) -> + Type = parse_type(drop_empty(C), Opts), + M0#method{type=Type}; +parse_member2(#xmlElement{name=name, content=[#xmlText{value=C}]}, Opts, M0) -> + Func = string:strip(C), + put(current_func, Func), + M0#method{name=name(Func,Opts)}; +parse_member2(#xmlElement{name=param, content=C},Opts,M0) -> + Parse = fun(Con, Ac) -> parse_param(Con, Opts, Ac) end, + Param0 = foldl(Parse, #param{}, drop_empty(C)), + add_param(Param0, Opts, M0); +parse_member2(_, _,M0) -> + M0. + +add_param(InParam, Opts, M0) -> + Param0 = case InParam#param.name of + undefined -> InParam#param{name="val"}; + _ -> InParam + end, + Param = case Param0#param.type of + #type{base={comp,_,_Comp}} -> Param0; + #type{base={class,_Class}} -> Param0; + #type{base={ref,_}} -> Param0; + #type{base={term,_}} -> Param0; + #type{base=List} when is_list(List) -> Param0; + %% Assume the pointer args to base types are out parameters + #type{by_val=false,single=true, mod=Mod} -> + case lists:member(const, Mod) of + true -> Param0; % But not if they are const + false -> Param0#param{in=false} + end; + _ -> Param0 + end, + add_param2(Param, Opts, M0). + +add_param2(P=#param{name=Name},#hs{fopt=FOpt},M0=#method{name=MName,params=Ps}) -> + case patch_param(MName, Name, P, FOpt) of + #param{where=nowhere} -> + M0#method{params=Ps}; + Patched -> + %% case MName of %% DEBUG + %% "GetSelections" -> + %% io:format("~p~n",[Patched]); + %% _ -> ignore + %% end, + %%ASSERT + case Patched#param.type of + #type{base=undefined} -> ?error({unknown_type,Patched}); + _ -> ok + end, + M0#method{params=[Patched|Ps]} + end. + +patch_param(Method, Name, P, Opt) -> + case gb_trees:lookup(Method,Opt) of + none -> P; + {value,NoArg} when is_integer(NoArg) -> P; + {value,Opts} when is_list(Opts) -> + case get_value(Name, Opts) of + undefined -> P; + List when is_list(List) -> + foldl(fun handle_param_opt/2,P,List); + Val -> + handle_param_opt(Val,P) + end + end. + +handle_param_opt(skip, P) -> P#param{where=c}; +handle_param_opt(nowhere, P) -> P#param{where=nowhere}; +handle_param_opt(skip_member, _P) -> throw(skip_member); +handle_param_opt({skip_member, Type}, P) -> + case P of + #param{type=#type{name=Type}} -> + throw(skip_member); + #param{type=Type} -> + throw(skip_member); + _ -> + P + end; +handle_param_opt({erl_func,_Name}, P) -> P; %% Handled elsewhere +handle_param_opt(in, P) -> P#param{in=true}; +handle_param_opt(out, P) -> P#param{in=false}; +handle_param_opt(both, P) -> P#param{in=both}; +handle_param_opt({def,Def},P) -> P#param{def=Def}; +handle_param_opt({type,Type}, P=#param{type=T}) -> P#param{type=T#type{name=Type}}; +handle_param_opt({single,Opt}, P=#param{type=T}) -> P#param{type=T#type{single=Opt}}; +handle_param_opt({base,Opt}, P=#param{type=T}) -> P#param{type=T#type{base=Opt}}; +handle_param_opt({c_only,Opt},P) -> P#param{where=c, alt=Opt}; +handle_param_opt({ref, pointer}, P=#param{type=T}) -> + P#param{type=T#type{by_val=false,ref={pointer, 1}}}; +handle_param_opt({mod,Mods}, P=#param{type=T=#type{mod=Mods0}}) -> + P#param{type=T#type{mod=Mods++Mods0}}. + +get_opt(Opt, Method, Sz, Opts) -> + case gb_trees:lookup(Method,Opts) of + none -> undefined; + {value, List} when is_list(List) -> + case get_value({Sz,Opt}, List, undefined) of + undefined -> + get_value(Opt, List, undefined); + Res -> Res + end + end. + +parse_param(#xmlElement{name=type,content=C},Opts,T) -> + Type = parse_type(drop_empty(C),Opts), + T#param{type=Type}; +parse_param(#xmlElement{name=declname,content=[C]},_Opts,T) -> + #xmlText{value=Name} = C, + T#param{name=Name}; +parse_param(#xmlElement{name=defval,content=[#xmlText{value=Def}]},_Opts,T) -> + T#param{def=string:strip(Def)}; +parse_param(#xmlElement{name=defval,content=Other},_Opts,T) -> + %% For defaults = (modifer wxType *) NULL + Def0 = foldr(fun(#xmlText{value=V}, Acc) -> V ++ Acc; + (#xmlElement{content=[#xmlText{value=V}]},Acc) -> + V ++ Acc + end, [], Other), +%% Def1 = lists:dropwhile(fun($)) -> false;(_) -> true end, Def0), +%% Def = string:strip(Def1), %% Drop type cast !! +%% io:format("Def ~s => ~s => ~s ~n", [Def0, Def1,string:strip(Def)]), + T#param{def=string:strip(Def0)}; +parse_param(#xmlElement{name=array,content=C},_Opts, T = #param{type=Type0}) -> + case Type0 of + _ when T#param.name=:="WXUNUSED" -> %% doxygen can't handle this macro + [#xmlText{value=RealVar}] = C, + [Name] = string:tokens(RealVar, "() "), + T#param{name=Name}; +%% #type{mod=[const]} -> +%% T#param{type=Type0#type{single=array, by_val=true}}; +%% _ -> +%% T#param{type=Type0#type{single=array, by_val=false}} + _ -> + T#param{type=Type0#type{single=array, by_val=true}} + end; +parse_param(#xmlElement{name=name,content=[C]}, _, T) -> + %% Attributes have this + #xmlText{value=Name} = C, + T#param{name=Name}; +%% Skipped: Attributes have this +parse_param(#xmlElement{name=definition}, _, T) -> T; +parse_param(#xmlElement{name=argsstring}, _, T) -> T; +parse_param(#xmlElement{name=briefdescription}, _, T) -> T; +parse_param(#xmlElement{name=detaileddescription}, _, T) -> T; +parse_param(#xmlElement{name=inbodydescription}, _, T) -> T; +parse_param(#xmlElement{name=location}, _, T) -> T; +parse_param(#xmlElement{name=referencedby}, _, T) -> T; +parse_param(Other=#xmlElement{name=Name}, _, T) -> + io:format("Unhandled Param ~p ~p ~n in ~p~n", [Name,Other,T]), + ?error(unhandled_param). + +parse_type([], _Opts) -> void; +parse_type(TypeInfo, Opts) -> + {Type,Info} = foldl(fun extract_type_info/2,{[],undefined},TypeInfo), + case Info of + {"member", Ref} -> + case string:tokens(Ref, "_") of + [FileName, "8h", _Id] -> + put({file_ref, FileName++"_8h"}, ref); + _ -> + ok + end; + _ -> ok + end, + + Empty = #type{}, + case parse_type2(reverse(Type),Info,Opts,#type{}) of + Empty -> ?error({strange_type, Type}); + Assert -> Assert + end. + +extract_type_info(#xmlText{value=Value}, {Acc, Info}) -> + {reverse(foldl(fun extract_type_info2/2, [], string:tokens(Value, " "))) ++ Acc, Info}; +extract_type_info(#xmlElement{name=ref,attributes=As,content=[#xmlText{value=V}]}, + {Acc,undefined}) -> + {value, #xmlAttribute{value = Refid}} = keysearch(refid,#xmlAttribute.name,As), + {value, #xmlAttribute{value = Kind}} = keysearch(kindref,#xmlAttribute.name,As), + {reverse(foldl(fun extract_type_info2/2, [], string:tokens(V, " "))) ++ Acc, + {Kind,Refid}}; +extract_type_info(What,Acc) -> + ?error({parse_error,What,Acc}). + +extract_type_info2("const",Acc) -> [const|Acc]; +extract_type_info2("*", [{by_ref,{pointer,N}}|Acc]) -> [{by_ref,{pointer,N+1}}|Acc]; +extract_type_info2("*", Acc) -> [{by_ref,{pointer,1}}|Acc]; +extract_type_info2("**", Acc) -> [{by_ref,{pointer,2}}|Acc]; +extract_type_info2("&", Acc) -> [{by_ref,reference}|Acc]; +extract_type_info2("WXDLLIMP" ++ _, Acc) -> Acc; +extract_type_info2(Type, Acc) -> [Type|Acc]. + +parse_type2(["void"], _Info, _Opts, _T) -> void; +parse_type2(["virtual"|R], _Info, _Opts, _T) -> + [] = R, + %% Bug in old doxygen virtual destructors have type virtual + void; +parse_type2(["wxe_cb"|R],Info,Opts, T) -> + parse_type2(R,Info,Opts,T#type{name=int,base=wxe_cb}); +parse_type2([const|R],Info,Opts,T=#type{mod=Mod}) -> + parse_type2(R,Info,Opts,T#type{mod=[const|Mod]}); +parse_type2(["unsigned"|R],Info,Opts,T=#type{mod=Mod}) -> + parse_type2(R,Info,Opts,T#type{mod=[unsigned|Mod]}); +parse_type2(["int"|R],Info,Opts, T) -> + parse_type2(R,Info,Opts,T#type{name=int,base=int}); +parse_type2(["char"|R],Info,Opts, T) -> + parse_type2(R,Info,Opts,T#type{name="char",base=int}); +parse_type2([N="size_t"|R], Info, Opts, T) -> + parse_type2(R,Info,Opts,T#type{name=N, base=int}); +parse_type2(["long"|R],Info, Opts, T) -> + parse_type2(R,Info,Opts,T#type{name=long,base=int}); +parse_type2(["float"|R],Info,Opts, T) -> + parse_type2(R,Info,Opts,T#type{name=float,base=float}); +parse_type2(["double"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=double,base=double}); +parse_type2([N="wxDouble"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base=double}); +parse_type2(["bool"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=bool,base=bool}); +parse_type2([N="wxWindowID"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base=int}); +parse_type2([N="wxTextCoord"|R],Info,Opts,T) -> %%long + parse_type2(R,Info,Opts,T#type{name=N,base=int}); +parse_type2([N="wxTextPos"|R],Info,Opts,T) -> %%long + parse_type2(R,Info,Opts,T#type{name=N,base=int}); +parse_type2([N="wxPrintQuality"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base=int}); +parse_type2([N="wxPaperSize"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base=int}); +parse_type2(["wxDataFormat"|_R],_Info,_Opts,T) -> + %% Hack Hack + T#type{name="wxDataFormatId",base=int}; +parse_type2([N="wxArrayInt"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base=int,single=array}); +parse_type2([N="wxArrayDouble"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base=double,single=array}); +parse_type2([N="wxTreeItemId"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base={ref,N}}); +parse_type2([N="wxArrayTreeItemIds"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base={ref,"wxTreeItemId"},single=array}); +parse_type2([N="wxTreeItemData"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name="wxETreeItemData",base={term,N}}); +parse_type2([N="wxClientData"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name="wxeErlTerm",base={term,N}}); +parse_type2([N="wxChar"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base=int}); +parse_type2(["wxUint32"|R],Info,Opts,T=#type{mod=Mod}) -> + parse_type2(R,Info,Opts,T#type{name=int,base=int,mod=[unsigned|Mod]}); +parse_type2([N="wxCoord"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base=int}); +parse_type2([N="wxPoint"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base={comp,N,[{int,"X"},{int,"Y"}]}}); +parse_type2([N="wxSize"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base={comp,N,[{int,"W"},{int,"H"}]}}); +parse_type2([N="wxGBPosition"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base={comp,N,[{int,"R"},{int,"C"}]}}); +parse_type2([N="wxGBSpan"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base={comp,N,[{int,"RS"},{int,"CS"}]}}); +parse_type2([N="wxGridCellCoords"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base={comp,N,[{int,"R"},{int,"C"}]}}); +parse_type2([N="wxGridCellCoordsArray"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base={comp,"wxGridCellCoords", + [{int,"R"},{int,"C"}]}, + single=array}); +parse_type2([N="wxRect"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base={comp,N,[{int,"X"},{int,"Y"}, + {int,"W"},{int,"H"}]}}); +parse_type2([N="wxColour"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N, + base={comp,N,[{int,"R"},{int,"G"},{int,"B"},{int,"A"}]}}); +parse_type2([N="wxColor"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name="wxColour", + base={comp,N,[{int,"R"},{int,"G"},{int,"B"},{int,"A"}]}}); + +parse_type2([N="wxPoint2DDouble"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N, + base={comp,N,[{double,"X"},{double,"Y"}]}}); +parse_type2([N="wxRect2DDouble"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N, + base={comp,N,[{double,"X"},{double,"Y"}, + {double,"W"},{double,"H"}]}}); + +parse_type2([N="wxDateTime"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N, + base={comp,N,[{int,"D"},{int,"Mo"},{int,"Y"}, + {int,"H"},{int,"Mi"},{int,"S"}]} + }); + +parse_type2([N="wxMouseState"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N, base={comp,N,{record, wxMouseState}}}); +parse_type2([N="wxHtmlLinkInfo"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N, base={comp,N,{record, wxHtmlLinkInfo}}}); +parse_type2([N="wxString"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base=string}); +parse_type2([N="wxArtClient"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base=string}); +parse_type2(["wxArtID"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name="wxString",base=string}); +parse_type2([N="wxFileName"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base=string}); +parse_type2([N="wxArrayString"|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{name=N,base=[int],single=array,by_val=true}); +parse_type2([{by_ref,Ref}|R],Info,Opts,T) -> + parse_type2(R,Info,Opts,T#type{ref=Ref,by_val=false}); +parse_type2([],_,_,T) -> T; + +parse_type2([N="wxImageList"|R],Info,Opts,T) -> %% ARRG breaks the following clause + parse_type2(R,Info,Opts,T#type{name=N,base={class,N}}); +parse_type2(L=[Name|R],I,Opts,T) -> + case reverse(Name) of + "tsiL" ++ RBase -> + parse_type2(R,I,Opts, + T#type{name=Name,base={class,reverse(RBase)},single=list}); + _ -> + parse_type3(L,I,Opts,T) + end. + +parse_type3(["wxNotebookPage"|R],I,Opts,T) -> + Xml = case I of + {_, Ref} -> Ref; + undefined -> undefined + end, + parse_type2(R,I,Opts,T#type{name="wxWindow",base={class,"wxWindow"},xml=Xml}); +parse_type3([N|R],I={"member",Ref},Opts,T) -> + Type = name(N,Opts), + ErlClass = special_name(Type), + case string:tokens(Ref, "_") of + ["class" ++ _] -> ignore; + Other -> + Inc0 = lists:takewhile(fun("8h") -> false;(_) -> true end,Other), + Inc = gen_util:args(fun(A) -> A end, "_", Inc0), +%% io:format("Inc ~s ~n", [Inc]), + put({include,Inc}, ref) + end, + case get_enum(Type) of + {_, undefined} -> + parse_type2(R,I,Opts,T#type{name=Type,base={class,ErlClass},xml=Ref}); + {TypeWOClass,#enum{}} -> + parse_type2(R,I,Opts,T#type{name=Type,base={enum,TypeWOClass},xml=Ref}) + end; +parse_type3([N = "wx"++_|R],I,Opts,T) -> + Xml = case I of + {_, Ref} -> Ref; + undefined -> undefined + end, + Class = name(N,Opts), + ErlClass = special_name(Class), + parse_type2(R,I,Opts,T#type{name=Class,base={class,ErlClass},xml=Xml}); +parse_type3([N="WXWidget"|R], Info,Opts, T) -> + parse_type2(R,Info,Opts,T#type{name=N,base=long}); +%% Let type errors be seen later because we don't know if these unhandled types +%% will be used. +parse_type3([Name|R],Info,Opts, T) -> + New = T#type{name={unhandled,Name,Info,get(current_class),get(current_func)}}, + parse_type2(R,Info,Opts, New). + +%%skipped(#method{method_type=constructor, type=void}, _Opts) -> true; +skipped(#method{}, #hs{skip=[]}) -> false; +skipped(#method{name=Name,params=P}, #hs{skip=Skip}) -> + AtomName = list_to_atom(Name), + Skipped = lists:member(AtomName, Skip) orelse + lists:member({AtomName,length(P)}, Skip), + %% io:format("~p ~p skipped ~p ~n", [AtomName, length(P),Skipped]), + Skipped. + +add_method(Ms0, NoArgs, Class, Opts) -> + Add = fun(M=#method{params=Ps0}, Acc) -> + case length(Ps0) of + NoArgs -> + [add_method2(M,Class,Opts)|Acc]; + _ when NoArgs =:= all -> + [add_method2(M,Class,Opts)|Acc]; + _ -> + Acc + end + end, + NewMs = lists:foldl(Add,[],Ms0), + Unique = filter_functions(reverse(NewMs), Opts), + erase(current_func), + foldl(fun(M,C=#class{methods=Ms}) when is_list(M) -> C#class{methods=[M|Ms]} end, + Class,reverse(Unique)). + +add_method2(M0=#method{name=Name,params=Ps0,type=T0},#class{name=CName,parent=Par},#hs{fopt=Opts}) -> + Type = case patch_param(Name, return, #param{type=T0}, Opts) of + #param{type = T0} -> + case patch_param(Name, {length(Ps0),return}, #param{type=T0}, Opts) of + #param{where=nowhere} -> void; + #param{type = Type0} -> Type0 + end; + #param{where=nowhere} -> void; + #param{type = Type0} -> Type0 + end, + + {Req,Opt} = lists:partition(fun(#param{def=Def}) -> Def == none end, + M0#method.params), + Ps = reverse(Ps0), + + IsStatic = case Par of + "static" -> static; + _ -> M0#method.method_type + end, + Where = case get_opt(where, Name, length(Ps), Opts) of + undefined -> both; + Other -> + Other + end, + M1 = M0#method{defined_in=CName, + min_arity = length(Req), + max_arity = length(Req) + if length(Opt) > 0 -> 1; true -> 0 end, + type = Type, + method_type = IsStatic, + where = Where, + id=next_id(func_id), + pre_hook = get_opt(pre_hook, Name, length(Ps), Opts), + post_hook = get_opt(post_hook, Name, length(Ps), Opts), + doc = get_opt(doc, Name, length(Ps), Opts) + }, + M = case Name of + CName -> + M1#method{method_type=constructor,name=CName, + type=constructor(CName), params=Ps}; + [$~|CName] -> + M1#method{method_type=destructor,name=Name, + params=[this(CName)|Ps]}; + _ -> + case M1#method.method_type of + static -> M1#method{params=Ps}; + member -> M1#method{params=[this(CName)|Ps]} + end + end, + M. + +this(Class) -> + #param{name="This",where=this, + type=#type{name=Class,base={class,Class},by_val=false,ref={pointer,1}}}. + +constructor(Class) -> + #type{name=Class,base={class,Class},by_val=false,ref=reference}. + +filter_functions(Parsed, Opts) -> + Left = foldl(fun(M0,Acc) -> + case skipped(M0, Opts) of + true -> Acc; + false -> + TF = extract_type_footprint(M0), + [TF|Acc] + end + end,[],Parsed), + Clean = remove_or_merge(lists:sort(Left),[],[]), + erl_skip_opt(reverse(Clean),[],[]). + +remove_or_merge([{A,{L,In,O1},M1}|Rest=[{A,{L,In,O2},M2}|_]],Acc1,Acc2) + when M1#method.method_type =:= M2#method.method_type -> + %% These are the same remove one of them. + case O1 =:= O2 of + true -> ok; + false -> + ?warning("Multiple out arguments of ~s:~s: ~p or ~p~n", + [get(current_class),M1#method.name, O1,O2]) + end, + remove_or_merge(Rest,Acc1,Acc2); +remove_or_merge([F={A,{Len,_,_},M1}|Rest],[{A,{Len,_,_},M2}|_]=Acc1,Acc2) + when M1#method.method_type =:= M2#method.method_type -> + NewAcc1 = maybe_merge(F,Acc1,[]), + remove_or_merge(Rest,NewAcc1,Acc2); +remove_or_merge([F|Rest],[],Acc2) -> + remove_or_merge(Rest,[F],Acc2); +remove_or_merge([F|Rest],Acc1,Acc2) -> + remove_or_merge(Rest,[F], [reverse(Acc1)|Acc2]); +remove_or_merge([],[], Acc2) -> Acc2; +remove_or_merge([],Acc1,Acc2) -> [reverse(Acc1)|Acc2]. + +erl_skip_opt([Ms|R],[],Acc2) -> + {Orig, Skipped} = erl_skip_opt2(Ms,[],[],[]), + erl_skip_opt(R,Orig,[Skipped|Acc2]); +erl_skip_opt(All=[Ms=[{_,{Len,_,_},_}|_]|R],Acc1=[{_,{N,_,_},_}|_], Acc2) -> + case Len =:= N+1 of + true -> + {Orig, Skipped} = erl_skip_opt2(Ms,[],[],Acc1), + erl_skip_opt(R,Orig,[Skipped++strip_ti(Acc1)|Acc2]); + false -> + erl_skip_opt(All, [], [strip_ti(Acc1)|Acc2]) + end; +erl_skip_opt([],Acc1,Acc2) -> [strip_ti(Acc1)|Acc2]. + +erl_skip_opt2([F={_,{N,In,_},M=#method{where=Where}}|Ms],Acc1,Acc2,Check) -> + case N > 0 andalso lists:last(In) =:= opt_list of + true when Where =/= merged_c, Where =/= taylormade -> + case Check of + [] -> + erl_skip_opt2(Ms,[F|Acc1],[M#method{where=erl_no_opt}|Acc2],[]); + _ -> + Skipped = reverse(tl(reverse(In))), + T = fun({_,{_,Args,_},_}) -> true =:= types_differ(Skipped,Args) end, + case lists:all(T, Check) of + true -> + erl_skip_opt2(Ms,[F|Acc1], + [M#method{where=erl_no_opt}|Acc2], + Check); + false -> + erl_skip_opt2(Ms,[F|Acc1],Acc2,Check) + end + end; + _ -> + erl_skip_opt2(Ms,[F|Acc1],Acc2,[]) + end; +erl_skip_opt2([],Acc1,Acc2,_) -> {Acc1,Acc2}. + +strip_ti(Ms) -> + [M || {_,{_,_,_},M} <- Ms]. + +maybe_merge(T1,[],Acc) -> reverse([T1|Acc]); +maybe_merge(F={A1,T1={Len,In1,O1},M1},[C={A2,T2={Len,In2,O2},M2}|Rest],Acc) -> + case types_differ(In1,In2) of + true -> maybe_merge(F,Rest,[C|Acc]); + {class,C1,C2} when O1 =:= O2 -> + {Merged,M2Mod} = merge_class_params(M1,M2,C1,C2), + reverse([{A1,T1,Merged},{A2,T2,M2Mod}|Acc]) ++ Rest; + false -> + ?warning("Argument clash in ~s:~s:~n ~p~nor ~p~n", + [get(current_class),M1#method.name,{In1,O1},{In2,O2}]), + [F|Rest++Acc] + end. + +merge_class_params(M1=#method{params=P1,id=Mi1},M2=#method{params=P2,id=Mi2},C1,C2) -> + Merged = merge_class_params2({class,C1},P1,Mi1,{class,C2},P2,Mi2), + {M1#method{params=Merged}, M2#method{where=merged_c}}. + +merge_class_params2(B1,[P1|R1],M1,B2,[P1|R2],M2) -> + [P1|merge_class_params2(B1,R1,M1,B2,R2,M2)]; +merge_class_params2(B1,[P1=#param{type=T1=#type{base=B1}}|R1],M1, + B2,[#param{type=T2=#type{base=B2}}|R2],M2) -> + [P1#param{type={merged,M1,T1,R1,M2,T2,R2}}|merge_class_params2(B1,R1,M1,B2,R2,M2)]; +merge_class_params2(B1,[P1|R1],_M1,B2,[P2|R2],_M2) -> + io:format("Merged Failed ~p ~p~n", [B1,B2]), + io:format(" ~p ~p~n ~p~p~n", [P1,R1,P2,R2]), + ?error(merged_failed); +merge_class_params2(_,[],_,_,[],_) -> + []. + +types_differ([C1|R1], [C2|R2]) when is_list(C1), is_list(C2) -> + types_differ(R1,R2); %% Different Classes +types_differ([C|R1], [C|R2]) -> + types_differ(R1,R2); +types_differ([{term,_}|R1], [_|R2]) -> + types_differ(R1,R2); +types_differ([_|R1], [{term,_}|R2]) -> + types_differ(R1,R2); +types_differ([{class,C1}|R1], [{class,C2}|R2]) -> + case types_differ(R1,R2) of + true -> + true; + false -> +%% _ -> + {class,C1,C2}; + {class,C1,C2} -> + {class,C1,C2}; + {class, _,_} -> + false + end; +types_differ([int|_], _) -> true; +types_differ(_, [int|_]) -> true; +types_differ([{class,_}|_], _) -> true; +types_differ(_, [{class,_}|_]) -> true; +types_differ([binary|_], _) -> true; +types_differ(_, [binary|_]) -> true; + +types_differ([list|R1], [opt_list|R2]) -> + types_differ(R1,R2); +types_differ([opt_list|R1], [list|R2]) -> + types_differ(R1,R2); +types_differ([C1|R1], [C2|R2]) when is_tuple(C1), is_tuple(C2) -> + (size(C1) =/= size(C2)) orelse types_differ(R1,R2); +types_differ([C1|_R1], [_C2|_R2]) when is_tuple(C1) -> + true; +types_differ([_C1|_R1], [C2|_R2]) when is_tuple(C2)-> + true; +types_differ([_C1|R1], [_C2|R2]) -> %% More cases? + types_differ(R1,R2); +types_differ([], []) -> + false. + +extract_type_footprint(M=#method{type=void,alias=A,params=Ps}) -> + {A,extract_type_footprint2(Ps, [], [], false), M}; +extract_type_footprint(M=#method{type=Type,alias=A,params=Ps}) -> + {A,extract_type_footprint2(Ps, [type_foot_print(Type)], [], false), M}. + +extract_type_footprint2([_P=#param{where=c, in=InArg}|R], Out, In, Opt) + when InArg =/= false -> + extract_type_footprint2(R, Out, In, Opt); +extract_type_footprint2([_P=#param{def=Def, in=InArg}|R], Out, In, _Opt) when Def =/= none, InArg =/= false -> + extract_type_footprint2(R, Out, In, true); +extract_type_footprint2([#param{in=false, type=Type}|Ps], Out, In, Opt) -> + extract_type_footprint2(Ps, [type_foot_print(Type)|Out], In, Opt); +extract_type_footprint2([#param{in=true, type=Type}|Ps], Out, In, Opt) -> + extract_type_footprint2(Ps, Out, [type_foot_print(Type)|In], Opt); +extract_type_footprint2([#param{in=both, type=Type}|Ps], Out, In, Opt) -> + TFP = type_foot_print(Type), + extract_type_footprint2(Ps, [TFP|Out], [TFP|In], Opt); + +extract_type_footprint2([], Out0, In, Opt) -> + Out = case Out0 of + [] -> void; + [One] -> One; + _ -> list_to_tuple(reverse(Out0)) + end, + if Opt -> + {length(In)+1,reverse([opt_list|In]),Out}; + true -> + {length(In), reverse(In),Out} + end. + +type_foot_print(#type{single=Single}) when Single =/= true -> list; +type_foot_print(#type{base=string}) -> list; +type_foot_print(#type{base=Base}) when is_list(Base) -> list; +type_foot_print(#type{base=long}) -> int; +type_foot_print(#type{base=binary}) -> binary; +type_foot_print(#type{base={binary,_}}) -> binary; +type_foot_print(#type{base=int}) -> int; +type_foot_print(#type{base=bool}) -> bool; +%%type_foot_print(#type{base=datetime}) -> datetime; +type_foot_print(#type{base=float}) -> float; +type_foot_print(#type{base=double}) -> float; +type_foot_print(#type{base=C={class,_}}) -> C; +type_foot_print(#type{base={enum,_}}) -> int; +type_foot_print(#type{base={ref,_}}) -> ref; +type_foot_print(#type{base={term,_}}) -> term; +type_foot_print(#type{base=eventType}) -> atom; +%% type_foot_print({Type,Str}) when is_list(Str) -> +%% type_foot_print(Type); +type_foot_print(#type{base={comp,_,R={record,_}}}) -> + R; +type_foot_print(#type{base={comp,_,Types}}) -> + TFL = map(fun({T,N}) when is_list(N) -> + case T of + double -> float; + _ -> T + end + end, Types), + list_to_tuple(TFL). +%type_foot_print(What) -> What. + + +translate_enums(Defs) -> + Res = [translate_enums1(Def) || Def <- Defs], + Consts = [Enum || Enum = {{enum,_},_} <- get()], + translate_constants(Consts, get(not_const), get(const_skip)), + put(gvars, [{Gvar,Class,next_id(const)} || {Gvar,Class} <- lists:sort(get(gvars))]), + Res. + +translate_enums1(C=#class{name=Name, methods=Ms0, attributes=As0}) -> + Ms = [translate_enums2(M, Name) || M <- Ms0], + As = [translate_enums3(A, Name) || A <- As0], + C#class{methods=Ms, attributes=As}. + +translate_enums2(M=#method{params=Ps0, type=T0},Class) -> + Ps = [translate_enums3(P, Class) || P <- Ps0], + T = translate_enums_type(T0,Class), + M#method{params=Ps,type=T}; +translate_enums2(Ms,Class) when is_list(Ms) -> + [translate_enums2(M,Class) || M <- Ms]. + +translate_enums3(P=#param{type=Type0},InClass) -> + Type = translate_enums_type(Type0,InClass), + P#param{type=Type}; +translate_enums3(InHer = {inherited, _},_InClass) -> + InHer. + +translate_enums_type(T=#type{base={class,C}},Class) -> + case get_enum(C,Class) of + {_, undefined} -> T; + {Enum, #enum{}} -> + %% io:format("ENUM Change class ~p to enum ~p~n", [C,Enum]), + T#type{base={enum, Enum}} + end; +translate_enums_type(T,_Class) -> T. + +translate_constants(Enums, NotConsts0, Skip0) -> + NotConsts = gb_sets:from_list(NotConsts0), + Skip = gb_sets:from_list(Skip0), + Consts0 = create_consts(lists:sort(Enums), Skip, NotConsts, []), + put(consts, gb_trees:from_orddict(lists:ukeysort(1,[{N,C}|| C = #const{name=N} <- Consts0]))). + +create_consts([{{enum, Name},Enum = #enum{vals=Vals}}|R], Skip, NotConsts, Acc0) -> + CC = fun(What, Acc) -> + create_const(What, Skip, NotConsts, Acc) + end, + Acc = case Vals of + undefined -> + ?warning("Missing Enum ~p ~p ~n",[Name, Enum]), + Acc0; + [] -> %% ?warning("Ignored Empty Enum list ~p ~n",[_Name]), + Acc0; + _ -> + foldl(CC, Acc0, lists:sort(Vals)) + end, + create_consts(R, Skip, NotConsts, Acc); +create_consts([],_,_,Acc) -> Acc. + +create_const({Name, Val}, Skip, NotConsts, Acc) -> + case gb_sets:is_member(Name, Skip) of + true -> Acc; + false -> + case gb_sets:is_member(Name, NotConsts) of + true -> + [#const{name=Name,val=next_id(const),is_const=false}|Acc]; + false -> + [#const{name=Name,val=Val,is_const=true}|Acc] +%% false -> +%% [#const{name=Name,val=Val}|Acc] + end + end. + +%%%%%%%%%%%%% +next_id(What) -> + Next = case get(What) of + undefined -> 100; + N -> N+1 + end, + put(What, Next), + Next. + +name([$~|Name], Opts) -> + [$~|name(Name,Opts)]; +name(Name0, #hs{alias=Alias}) -> + Name = case reverse(Name0) of + "esaBlooT" ++ _ -> %% Arrg uses base + Name0; + "esaBelbaTdirG" ++ _ -> %% Arrg uses base + Name0; + "esaBrekciP" ++ _ -> %% Arrg uses base + Name0; + "esaB" ++ Rest when hd(Name0) == $w -> + %% Arrg Some decl uses base class directly + reverse(Rest); + _F -> + Name0 + end, + get_value(Name,Alias,Name). + +special_name("wxIconLocation") -> "wx"; +special_name("wxToolBarToolBase") -> "wx"; +special_name("wxObject") -> "wx"; +special_name("wxValidator") -> "wx"; % XXXXX +%% special_name("wxTreeItemData") -> "wx"; % XXXXX +%% special_name("wxTreeItemId") -> "wx"; +%% special_name("wxDataObject") -> "wx"; +special_name(Other) -> Other. + +drop_empty(List) -> + filter(fun(#xmlText { value = Text}) -> + string:strip(Text) =/= ""; + (_)-> + true + end, List). + +%%% Enums +parse_enums(Files) -> + DontSearch = ["wxchar","filefn", "platform", "strconv", "filename", + "buffer", "string", "debug", "platinfo"], + %% Arg need to patch some specials, atleast for wx-2.6 + ExtraSearch = ["gtk_2glcanvas", "generic_2splash"], + parse_enums(Files ++ ExtraSearch,gb_sets:from_list(DontSearch)). + +parse_enums([File|Files], Parsed) -> + case gb_sets:is_member(File,Parsed) of + false -> + FileName = filename:join(["wx_xml",File ++ "_8h.xml"]), +%% io:format("Parse Enums in ~s ~n", [FileName]), + case xmerl_scan:file(FileName, [{space, normalize}]) of + {error, enoent} -> + parse_enums(Files, gb_sets:add(File,Parsed)); + {Doc, _} -> + ES = "./compounddef/sectiondef/memberdef[@kind=\"enum\"]", + AM = xmerl_xpath:string(ES, Doc), + lists:foreach(fun(Def) -> extract_enum(Def, undefined, File) end, AM), + + DS = "./compounddef/sectiondef/memberdef[@kind=\"define\"]", + Defs = xmerl_xpath:string(DS, Doc), + extract_defs(Defs,File), + + INCs = xmerl_xpath:string("./compounddef/includes/text()", Doc), + New = [reverse(tl(tl(reverse(Inc)))) || + #xmlText{value="wx/"++Inc} <- INCs], + %% io:format("Scan enums from ~p ~n", [File]), + parse_enums(New ++ Files, gb_sets:add(File,Parsed)) + end; + true -> + parse_enums(Files,Parsed) + end; +parse_enums([],_) -> ok. + +extract_enum(#xmlElement{name=memberdef,content=C}, Class, File) -> + {Name0,Vals0} = extract_enum2(C,undefined,0,[]), + {Vals,Name} = + if + hd(Name0) =:= $@, Class =:= undefined -> + {Vals0, Name0 ++ "_" ++ File}; + Class =:= undefined-> + {Vals0, Name0}; + true -> + {[{Class++"::"++N,V} || {N,V} <- Vals0], {Class,Name0}} + end, + case get({enum, Name}) of + undefined -> +%% io:format("1Enum name ~p~n", [Name]), +%% [io:format(" ~s ~p~n", [D,V]) || {D,V} <- Vals], + put({enum, Name}, #enum{vals=Vals}); + E = #enum{vals=undefined} -> +%% io:format("2Enum name ~p~n", [Name]), +%% [io:format(" ~s ~p~n", [D,V]) || {D,V} <- Vals], + put({enum, Name}, E#enum{vals=Vals}); + #enum{vals=Vals} -> ok; +%% io:format("Same? ~p ~n", [PVals == Vals]) + #enum{vals=OldVals} -> + io:format("Enum ~p in ~p ~p ~p~n", [Name,Class,get(current_class),get(current_func)]), + io:format("New ~p~n", [Vals]), + io:format("Old ~p~n", [OldVals]), + erlang:error({enum_mismatch,Name,Vals,OldVals}) + end, + ok. + +extract_enum2([#xmlElement{name=name,content=[#xmlText{value=Name}]}|R],_,Id,Acc0) -> + extract_enum2(R,Name,Id,Acc0); + +extract_enum2([#xmlElement{name=enumvalue,content=C}|R], N,Id,Acc0) -> + {Acc,NewId} = extract_enum3(C,Id,Acc0), + extract_enum2(R, N, NewId, Acc); +extract_enum2([_|R], N, Id, Acc) -> + extract_enum2(R, N, Id, Acc); +extract_enum2([], N, _Id, Acc) -> + {N, reverse(Acc)}. + +extract_enum3([#xmlElement{name=name,content=[#xmlText{value=Name}]}|R], Id, Acc) -> + case lists:keymember(Name, 1, Acc) of + true -> %% Doxygen double includes some defs. + {Acc,Id}; + false -> + case Id of + This = {Str,Num} -> + extract_enum3(R, {Str, Num+1}, [{Name,This}|Acc]); + Val -> + extract_enum3(R, Val+1, [{Name,Val}|Acc]) + end + end; + +extract_enum3([#xmlElement{name=initializer, + content=Cs=[#xmlText{}|_]}|_],_Id,[{Name,_}|Acc]) -> + + String = lists:append([string:strip(C#xmlText.value) || C <- Cs]), + + Val0 = gen_util:tokens(String,"<& "), + + try + case Val0 of + ["0x" ++ Val1] -> + Val = http_util:hexlist_to_integer(Val1), + {[{Name, Val}|Acc], Val+1}; + [Single] -> + Val = list_to_integer(Single), + {[{Name, Val}|Acc], Val+1}; + ["1", "<<", Shift] -> + Val = 1 bsl list_to_integer(Shift), + {[{Name, Val}|Acc], Val+1}; + [_Str, "+", _What] -> + Val = lists:append(Val0), + {[{Name, {Val, 0}}|Acc], {Val,1}}; + _What -> + %% io:format("~p Name ~p ~p~n",[?LINE, Name, Val0]), + throw(below) + end + catch _:_ -> + {[{Name,{String,0}}|Acc], {String,1}} + end; +extract_enum3([_|R], Id, Acc) -> + extract_enum3(R, Id, Acc); +extract_enum3([], Id, Acc) -> + {Acc, Id}. + +extract_defs(Defs, File) -> + case foldl(fun extract_defs2/2, {[], gb_sets:empty()}, Defs) of + [] -> ok; + {Vals,_Skip} -> +%% io:format("Defs file ~p~n", [File]), +%% [io:format(" ~s ~p~n", [D,V]) || {D,V} <- Vals, not is_integer(V)] + put({enum, {define,"From " ++ File ++ ".h"}}, #enum{vals=Vals}) + end. + +extract_defs2(#xmlElement{name=memberdef,content=C},{Acc,Skip}) -> + try + Res = {Name,_} = extract_def(C,undefined,Skip), + case gb_sets:is_member(Name,Skip) orelse lists:keymember(Name, 1, Acc) of + true -> {Acc,Skip}; + false -> {[Res | Acc], Skip} + end + catch throw:SkipName -> {Acc, gb_sets:add(SkipName,Skip)} + end. + +extract_def([#xmlElement{name=name,content=[#xmlText{value=Name}]}|R], _N, Skip) -> + case Name of + "wxUSE" ++ _ -> + throw(Name); + "wx" ++ _ -> + extract_def(R, Name, Skip); + _ -> + throw(Name) + end; +extract_def([#xmlElement{name=param}|_],Name,_) -> + throw(Name); +extract_def([#xmlElement{name=initializer,content=[#xmlText{value=Val0}]}|_],N,Skip) -> + case Val0 of + "0x" ++ Val1 -> {N, http_util:hexlist_to_integer(Val1)}; + _ -> + try + Val = list_to_integer(Val0), + {N, Val} + catch _:_ -> + case def_is_ok(Val0, Skip) of + false -> + throw(N); + NVal when is_integer(NVal) -> + {N, NVal}; + NVal -> + {N, {NVal,0}} + end + end + end; +extract_def([_|R],N,Skip) -> + extract_def(R,N,Skip); +extract_def(_,N,_) -> + throw(N). + +def_is_ok(Name, Skip) -> + Toks = gen_util:tokens(Name,"()| \\:"), + R = def_is_ok(Toks, Skip, []), +% io:format("~s -> ~p~n", [Name,R]), + R. + +def_is_ok([], _Skip, [")",Int, "("]) -> Int; +def_is_ok([], _Skip, Acc) -> lists:append(reverse(Acc)); +def_is_ok([N="wx"++_|R],Skip,Acc) -> + case gb_sets:is_member(N,Skip) of + true -> false; + false -> def_is_ok(R,Skip,[N|Acc]) + end; +def_is_ok(["0x"++Val|R],Skip,Acc) -> + def_is_ok(R,Skip,["16#" ++ Val|Acc]); +def_is_ok([N="|"|R], Skip, Acc) -> + def_is_ok(R,Skip,[N|Acc]); +def_is_ok([N="("|R], Skip, Acc) -> + def_is_ok(R,Skip,[N|Acc]); +def_is_ok([N=")"|R], Skip, Acc) -> + def_is_ok(R,Skip,[N|Acc]); +def_is_ok([":"|_], _Skip, _Acc) -> + false; +def_is_ok([N|R],Skip,Acc) -> + case catch list_to_integer(N) of + {'EXIT', _} -> false; + Int -> def_is_ok(R,Skip,[Int|Acc]) + end. + +get_enum(Type0) when is_list(Type0) -> + case string:tokens(Type0,":") of + [Type] -> + {Type, get({enum,Type})}; + [Class,Type] -> + get_enum(Type,Class) + end; +get_enum({Class,Type}) -> + get_enum(Type,Class). + +get_enum(Type,Class) -> + case get({enum,Type}) of + undefined -> + {{Class,Type},get({enum, {Class,Type}})}; + Res = #enum{} -> + {Type,Res} + end. diff --git a/lib/wx/api_gen/wx_gen.hrl b/lib/wx/api_gen/wx_gen.hrl new file mode 100644 index 0000000000..b34d399358 --- /dev/null +++ b/lib/wx/api_gen/wx_gen.hrl @@ -0,0 +1,88 @@ +%% +%% %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% +-record(class, + { + name = undefined, + parent = undefined, + methods = [], + attributes = [], + event = false, + file = undefined, + options = undefined, + abstract = false, + id, % Unique integer identifer + doc + }). + +-record(method, + { + name = undefined, % real name + alias = undefined, % erlang func name + type = void, % method type + min_arity = undefined, % Required args + max_arity = undefined, % Optional args + defined_in = undefined, % + params = [], % arguments to the function + method_type = member, % kind of method, e.g constructor + where = both, % Erl or c or both + id = undefined, % Id (integer) + doc, % Extra documentation + virtual, % Is virtual? + pre_hook, % Pre hook before call in c-code + post_hook % Post hook after call in c-code + } + ). + +-record(param, + { + name = undefined, + type = undefined, + def = none, + in = true, + where = both, % both in c and erl or only in either + prot = public, % only used by attributes + alt = undefined,% c-only alternative usually a length indicator + acc % access function if protected and needed + }). + +-record(type, + { + name = undefined, % typename + base = undefined, % basename int, char, float .. + by_val = true, % or false = by_ref + single = true, % Single or array (list) + mod = [], % const ... + ref = undefined, % pointer or reference + xml = undefined % xml identity + } + ). + +-record(enum, {skip="", as_atom=false, vals}). +-record(const,{name,val,enum,is_const}). + +-define(error(What), + erlang:error({{?MODULE,?LINE},{get(current_class),get(current_func)},What})). + +-define(warning(Str,Args), + io:format("~p:~p Warning:"++Str, [?MODULE,?LINE] ++ Args)). + +%-ifdef(TRACE_COMMENT). +%-define(WTC(X), w("// ~p:~p ~p~n",[?MODULE, ?LINE, X])). +%-else. +-define(WTC(X), void). +%-endif. 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. diff --git a/lib/wx/api_gen/wx_gen_erl.erl b/lib/wx/api_gen/wx_gen_erl.erl new file mode 100644 index 0000000000..64c11baec1 --- /dev/null +++ b/lib/wx/api_gen/wx_gen_erl.erl @@ -0,0 +1,1272 @@ +%% +%% %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_erl.erl +%%% Author : Dan Gudmundsson <[email protected]> +%%% Description : +%%% +%%% Created : 25 Jan 2007 by Dan Gudmundsson <[email protected]> +%%%------------------------------------------------------------------- + +-module(wx_gen_erl). + +-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, erl_copyright/0, w/2, + args/3, args/4, strip_name/2]). + +gen(Defs) -> + [put({class,N},C) || C=#class{name=N} <- Defs], + gen_unique_names(Defs), + gen_event_recs(), + gen_enums_ints(), + [gen_class(Class) || Class <- Defs], + gen_funcnames(). + +gen_class(Class) -> + try + gen_class1(Class) + catch throw:skipped -> + Class + end. + +gen_class1(C=#class{name=Name,parent="static",methods=Ms,options=_Opts}) -> + open_write("../src/gen/wx_misc.erl"), + put(current_class, Name), + erl_copyright(), + w("", []), + w("%% This file is generated DO NOT EDIT~n~n", []), + w("%% @doc See external documentation: " + "<a href=\"http://www.wxwidgets.org/manuals/stable/wx_miscellany.html\">Misc</a>.\n\n",[]), + + w("%% This module contains wxWidgets utility functions.~n~n", []), + w("-module(wx_misc).~n", []), + w("-include(\"wxe.hrl\").~n",[]), + %% w("-compile(export_all).~n~n", []), %% XXXX remove ??? + + Exp = fun(M) -> gen_export(C,M) end, + ExportList = lists:usort(lists:append(lists:map(Exp,reverse(Ms)))), + w("-export([~s]).~n~n", [args(fun(EF) -> EF end, ",", ExportList, 60)]), + + + Gen = fun(M) -> gen_method(Name,M) end, + NewMs = lists:map(Gen,reverse(Ms)), + close(), + erase(current_class), + C#class{methods=NewMs}; + +gen_class1(C=#class{name=Name,parent=Parent,methods=Ms,options=Opts}) -> + case Opts of + ["ignore"] -> throw(skipped); + _ -> ok + end, + open_write("../src/gen/"++Name++".erl"), + put(current_class, Name), + erl_copyright(), + w("", []), + w("%% This file is generated DO NOT EDIT~n~n", []), + + case lists:member(taylormade, Opts) of + true -> + {ok, Bin} = file:read_file(filename:join([wx_extra, Name++".erl"])), + w("~s~n", [binary_to_list(Bin)]), + NewMs = Ms; + false -> + w("%% @doc See external documentation: " + "<a href=\"http://www.wxwidgets.org/manuals/stable/wx_~s.html\">~s</a>.\n", + [lowercase_all(Name), Name]), + + case C#class.doc of + undefined -> ignore; + Str -> w("%%~n%% ~s~n~n%%~n", [Str]) + end, + + case C#class.event of + false -> ignore; + Evs -> + EvTypes = [event_type_name(Ev) || Ev <- Evs], + EvStr = args(fun(Ev) -> "<em>"++Ev++"</em>" end, ", ", EvTypes), + + w("%% <dl><dt>Use {@link wxEvtHandler:connect/3.} with EventType:</dt>~n",[]), + w("%% <dd>~s</dd></dl>~n", [EvStr]), + w("%% See also the message variant {@link wxEvtHandler:~s(). #~s{}} event record type.~n", + [event_rec_name(Name),event_rec_name(Name)]), + w("%%~n",[]), + ok + end, + + Parents = parents(Parent), + case [P || P <- Parents, P =/= root, P =/= object] of + [] -> ignore; + Ps -> + w("%% <p>This class is derived (and can use functions) from: ~n", []), + [w("%% <br />{@link ~s}~n", [P]) || P <- Ps], + w("%% </p>~n",[]) + end, + w("%% @type ~s(). An object reference, The representation is internal~n",[Name]), + w("%% and can be changed without notice. It can't be used for comparsion~n", []), + w("%% stored on disc or distributed for use on other nodes.~n~n", []), + w("-module(~s).~n", [Name]), + w("-include(\"wxe.hrl\").~n",[]), + %% w("-compile(export_all).~n~n", []), %% XXXX remove ??? + %% w("-compile(nowarn_unused_vars).~n~n", []), %% XXXX remove ??? + Exp = fun(M) -> gen_export(C,M) end, + ExportList = lists:usort(lists:append(lists:map(Exp,reverse(Ms)))), + w("-export([~s]).~n~n", [args(fun(EF) -> EF end, ",", ExportList, 60)]), + w("%% inherited exports~n",[]), + Done0 = ["Destroy", "New", "Create", "destroy", "new", "create"], + Done = gb_sets:from_list(Done0 ++ [M|| #method{name=M} <- lists:append(Ms)]), + {_, InExported} = gen_inherited(Parents, Done, []), + w("-export([~s]).~n~n", [args(fun(EF) -> EF end, ",", + lists:usort(["parent_class/1"|InExported]), + 60)]), + + w("%% @hidden~n", []), + parents_check(Parents), + + Gen = fun(M) -> gen_method(Name,M) end, + NewMs = lists:map(Gen,reverse(Ms)), + gen_dest(C, Ms), + + gen_inherited(Parents, Done, true) + end, + + close(), + erase(current_class), + C#class{methods=NewMs}. + + +parents("root") -> [root]; +parents("object") -> [object]; +parents(Parent) -> + case get({class,Parent}) of + #class{parent=GrandParent} -> + [Parent|parents(GrandParent)]; + undefined -> + ?warning("unknown parent of ~p~n",[Parent]), + [Parent] + end. + +parents_check([object]) -> + w("parent_class(_Class) -> erlang:error({badtype, ?MODULE}).~n~n",[]); +parents_check([root]) -> + w("parent_class(_Class) -> erlang:error({badtype, ?MODULE}).~n~n",[]); +parents_check([Parent|Ps]) -> + w("parent_class(~s) -> true;~n",[Parent]), + parents_check(Ps). + +check_class(#type{base={class,"wx"}}) -> ok; +check_class(#type{base={class,Name},xml=Xml}) -> + case get({class,Name}) of + undefined -> + case get({enum, Name}) of + undefined -> + case Xml of + "class" ++ _ -> + ?warning("~s:~s: Class ~p used but not defined~n", + [get(current_class),get(current_func),Name]); + _ -> + ?warning("~s:~s: Class ~p used but not defined~n (see ~p)~n", + [get(current_class),get(current_func),Name, Xml]) + end; + _ -> + ?warning("~s:~s: Class ~p used is enum~n", + [get(current_class),get(current_func),Name]) + end; + _ -> ok + end. + +gen_export(#class{name=Class,abstract=Abs},Ms0) -> + RemoveC = fun(#method{where=merged_c}) -> false;(_Other) -> true end, + Res = filter(RemoveC, Ms0), + case Res of + [] -> []; + [M=#method{where=taylormade}|_] -> + [taylormade_export(Class, M)]; + Ms -> + GetF = fun(#method{method_type=constructor,where=W,params=Ps}) -> + {Args,Opts} = split_optional(Ps), + OptLen = case Opts of + [] -> 0; + _ when W =:= erl_no_opt -> 0; + _ -> 1 + end, + "new/" ++ integer_to_list(length(Args)+OptLen); + (#method{method_type=destructor}) -> + case Abs of + true -> []; + _ -> "destroy/1" + end; + (#method{name=N,alias=A,where=W, params=Ps}) -> + {Args,Opts} = split_optional(Ps), + OptLen = case Opts of + [] -> 0; + _ when W =:= erl_no_opt -> 0; + _ -> 1 + end, + erl_func_name(N,A) ++ "/" ++ integer_to_list(length(Args) + OptLen) + end, + lists:map(GetF, Ms) + end. + + +gen_method(Class,Ms0) -> + RemoveC = fun(#method{where=merged_c}) -> false;(_Other) -> true end, + Res = filter(RemoveC, Ms0), + case Res of + [] -> Ms0; + [M=#method{where=taylormade}|_] -> + taylormade_func(Class, M), + Ms0; + Ms -> + gen_doc(Class,Ms), + gen_method1(Ms), + Ms0 + end. + +gen_method1([M=#method{method_type=destructor}]) -> + %% Skip now do destructors later + M; +gen_method1([M0]) -> + gen_method2(M0), + w(".~n~n",[]); +gen_method1([M0|Ms]) -> + gen_method2(M0), + w(";~n",[]), + gen_method1(Ms). + +gen_method2(M=#method{name=N,alias=A,params=Ps0,where=erl_no_opt,method_type=MT}) -> + put(current_func, N), + Ps = [patch_param(P,classes) || P <- Ps0], + w("~n", []), + gen_function_clause(erl_func_name(N,A),MT,Ps,[],[name_type]), + w(" ", []), + gen_function_clause(erl_func_name(N,A),MT,Ps,empty_list,[no_guards,name_only]), + M; +gen_method2(M=#method{name=N,alias=A,params=Ps,type=T,method_type=MT,id=MethodId}) -> + put(current_func, N), + {Args, Optional} = split_optional(Ps), + gen_function_clause(erl_func_name(N,A),MT, Args, Optional, []), + MId = arg_type_tests(Args, "?" ++ get_unique_name(MethodId)), + {MArgs,Align} = marshal_args(Args), + MOpts = marshal_opts(Optional, Align, Args), + case have_return_vals(T, Ps) of + _ when MT =:= constructor -> + w(" wxe_util:construct(~s,~n <<~s~s>>)", [MId, MArgs,MOpts]); + true -> + w(" wxe_util:call(~s,~n <<~s~s>>)", [MId, MArgs,MOpts]); + false -> + w(" wxe_util:cast(~s,~n <<~s~s>>)", [MId, MArgs,MOpts]) + end, + erase(current_func), + M. + +gen_dest(#class{name=CName,abstract=Abs}, Ms) -> + case Abs of + true -> + ignore; + false -> + case lists:keysearch(destructor,#method.method_type, lists:append(Ms)) of + {value, #method{method_type=destructor, id=Id}} -> + case hd(reverse(parents(CName))) of + object -> + gen_dest2(CName, object); + root -> + gen_dest2(CName, Id) + end; + false -> + erlang:error({no_destructor_found, CName}) + end + end. + +gen_dest2(Class, Id) -> + w("%% @spec (This::~s()) -> ok~n", [Class]), + w("%% @doc Destroys this object, do not use object again~n", []), + w("destroy(Obj=#wx_ref{type=Type}) -> ~n", []), + w(" ?CLASS(Type,~s),~n",[Class]), + case Id of + object -> + w(" wxe_util:destroy(?DESTROY_OBJECT,Obj),~n ok.~n", []); + _ -> + w(" wxe_util:destroy(?~s,Obj),~n ok.~n", [get_unique_name(Id)]) + end, + ok. + +gen_inherited([root], Done, Exported) -> {Done, Exported}; +gen_inherited([object], Done, Exported) -> {Done, Exported}; +gen_inherited([Parent|Ps], Done0, Exported0) -> + #class{name=Class, methods=Ms} = get({class,Parent}), + case is_list(Exported0) of + false -> w(" %% From ~s ~n", [Class]); + true -> ignore + end, + {Done,Exported} = gen_inherited_ms(Ms, Class, Done0, gb_sets:empty(), Exported0), + gen_inherited(Ps, gb_sets:union(Done,Done0), Exported). + +gen_inherited_ms([[#method{name=Name,alias=A,params=Ps0,where=W,method_type=MT}|_]|R], + Class,Skip,Done, Exported) + when W =/= merged_c -> + case gb_sets:is_member(Name,Skip) of + false when MT =:= member, Exported =:= true -> + Ps = [patch_param(P,all) || P <- Ps0], + Opts = if W =:= erl_no_opt -> []; + true -> + [Opt || Opt = #param{def=Def,in=In, where=Where} <- Ps, + Def =/= none, In =/= false, Where =/= c] + end, + w("%% @hidden~n", []), + gen_function_clause(erl_func_name(Name,A),MT,Ps,Opts,[no_guards,name_only]), + w(" -> ~s:", [Class]), + gen_function_clause(erl_func_name(Name,A),MT,Ps,Opts,[no_guards,name_only]), + w(".~n", []), + gen_inherited_ms(R,Class, Skip, gb_sets:add(Name,Done), Exported); + false when MT =:= member, is_list(Exported) -> + {Args,Opts} = split_optional(Ps0), + OptLen = case Opts of + [] -> 0; + _ when W =:= erl_no_opt -> 0; + _ -> 1 + end, + Export = erl_func_name(Name,A) ++ "/" ++ integer_to_list(length(Args) + OptLen), + gen_inherited_ms(R,Class,Skip, gb_sets:add(Name,Done), [Export|Exported]); + _ -> + gen_inherited_ms(R,Class, Skip, Done, Exported) + end; +gen_inherited_ms([[_|Check]|R],Class,Skip, Done0,Exp) -> + gen_inherited_ms([Check|R],Class,Skip, Done0,Exp); +gen_inherited_ms([[]|R],Class,Skip,Done0,Exp) -> + gen_inherited_ms(R,Class,Skip,Done0,Exp); +gen_inherited_ms([], _, _Skip, Done,Exp) -> {Done,Exp}. + + +%%%%%%%%%%%%%%% + +taylormade_func(Class, #method{name=Name, id=Id}) -> + {ok, Bin} = file:read_file(filename:join([wx_extra, Class ++".erl"])), + Str0 = binary_to_list(Bin), + {match, [Str1]} = re:run(Str0, "<<"++Name++"(.*)"++Name++">>", + [dotall, {capture, all_but_first, list}]), + + w(Str1, ["?" ++ get_unique_name(Id)]), + ok. + +taylormade_export(Class, #method{name=Name}) -> + {ok, Bin} = file:read_file(filename:join([wx_extra, Class ++".erl"])), + Str0 = binary_to_list(Bin), + {match, [Str1]} = re:run(Str0, "<<EXPORT:"++Name++"(.*)"++Name++":EXPORT>>", + [dotall, {capture, all_but_first, list}]), + Str1. + +%%%%%%%%%%%%%%% + +arg_type_tests([P|Ps], Mid0) -> + case arg_type_test(P,"\n",Mid0) of + Mid0 -> + arg_type_tests(Ps, Mid0); + Mid -> %% Already checked the other args + Mid + end; +arg_type_tests([],Mid) -> Mid. + +arg_type_test(#param{where=c}, _, Acc) -> + Acc; +arg_type_test(#param{name=Name0,in=In,type=#type{base={class,T},single=true},def=none}, + EOS,Acc) when In =/= false -> + Name = erl_arg_name(Name0), + w(" ?CLASS(~sT,~s),~s", [Name,T,EOS]), + Acc; +arg_type_test(#param{name=Name0,in=In,type=#type{base={class,T}}, def=none},EOS,Acc) + when In =/= false -> + Name = erl_arg_name(Name0), + w(" [?CLASS(~sT,~s) || #wx_ref{type=~sT} <- ~s],~s", [Name,T,Name,Name,EOS]), + Acc; +arg_type_test(#param{name=Name0,def=none,in=In, + type={merged, + M1, #type{base={class,T1},single=true},Ps1, + M2, #type{base={class,T2},single=true},Ps2}}, EOS, _Acc) + when In =/= false -> + Name = erl_arg_name(Name0), + Opname = Name++"OP", + w(" ~s = case ?CLASS_T(~sT,~s) of~n true ->\n ", [Opname,Name,T1]), + lists:foreach(fun(Param) -> arg_type_test(Param,"\n ", ignore) end, + element(1,split_optional(Ps1))), + w("?~s;~n",[get_unique_name(M1)]), + w(" _ -> ?CLASS(~sT,~s),\n ",[Name,T2]), + {Ps21,_} = split_optional(patchArgName(Ps2,Ps1)), + lists:foreach(fun(Param) -> arg_type_test(Param,"\n ", ignore) end, + Ps21), + w("?~s\n end,~s",[get_unique_name(M2),EOS]), + Opname; +arg_type_test(#param{name=Name0, type=#type{base=eventType}}, EOS, Acc) -> + Name = erl_arg_name(Name0), + w(" ~sBin = list_to_binary([atom_to_list(~s)|[0]]),~s", [Name,Name,EOS]), + w(" ThisTypeBin = list_to_binary([atom_to_list(ThisT)|[0]]),~s", [EOS]), + Acc; +arg_type_test(#param{name=Name0,def=none,type=#type{base={term,_}}}, EOS, Acc) -> + Name = erl_arg_name(Name0), + w(" wxe_util:send_bin(term_to_binary(~s)),~s", [Name,EOS]), + Acc; +arg_type_test(#param{name=Name0,type=#type{base=binary}},EOS,Acc) -> + Name = erl_arg_name(Name0), + w(" wxe_util:send_bin(~s),~s", [Name,EOS]), + Acc; +arg_type_test(#param{name=Name0,type=#type{name=Type,base=Base,single=Single}},EOS,Acc) -> + if + Type =:= "wxArtClient", Single =:= true -> + Name = erl_arg_name(Name0), + w(" ~s_UC = unicode:characters_to_binary([~s, $_, $C,0]),~s", + [Name,Name, EOS]); + Base =:= string orelse (Type =:= "wxChar" andalso Single =/= true) -> + Name = erl_arg_name(Name0), + w(" ~s_UC = unicode:characters_to_binary([~s,0]),~s", [Name,Name,EOS]); + Type =:= "wxArrayString" -> + Name = erl_arg_name(Name0), + w(" ~s_UCA = [unicode:characters_to_binary([~sTemp,0]) || ~s", + [Name,Name, EOS]), + w(" ~sTemp <- ~s],~s", [Name,Name,EOS]); + true -> %% Not a string + ignore + end, + Acc; +arg_type_test(_,_,Acc) -> Acc. + +patchArgName([Param|R1], [#param{name=Name}|R2]) -> + [Param#param{name=Name}|patchArgName(R1,R2)]; +patchArgName([],[]) -> []. + +have_return_vals(void, Ps) -> + lists:any(fun(#param{in=In}) -> In =/= true end, Ps); +have_return_vals(#type{}, _) -> true. + +gen_function_clause(Name0,MT,Ps,Optional,Variant) -> + PArg = fun(Arg) -> + case lists:member(name_only, Variant) of + true -> func_arg_name(Arg); + false -> + case lists:member(name_type, Variant) of + true -> + Name = func_arg_name(Arg), + case func_arg(Arg) of + Name -> Name; + Typed -> Name ++ "=" ++ Typed + end; + false -> + func_arg(Arg) + end + end + end, + Args = args(PArg, ",", Ps), + Name = case MT of constructor -> "new"; _ -> Name0 end, + w("~s(~s",[Name,Args]), + Opts = case Optional of + [] -> ""; + empty_list when Args =:= [] -> "[]"; + empty_list -> ", []"; + _ when Args =:= [] -> "Options"; + _ -> ", Options" + end, + w("~s)", [Opts]), + case lists:member(no_guards, Variant) of + true -> ok; + false -> + Guards = args(fun guard_test/1, ",", Ps), + if + Guards =:= [], Opts =:= "" -> w(" ->~n", []); + Guards =:= [] -> w("~n when is_list(Options) ->~n", []); + Opts =:= "" -> w("~n when ~s ->~n", [Guards]); + true -> w("~n when ~s,is_list(Options) ->~n", [Guards]) + end + end. + +split_optional(Ps) -> + split_optional(Ps, [], []). +split_optional([P=#param{def=Def,in=In, where=Where}|Ps], Standard, Opts) + when Def =/= none, In =/= false, Where =/= c -> + split_optional(Ps, Standard, [P|Opts]); +split_optional([P=#param{def=Def,in=In, where=Where}|Ps], Standard, Opts) + when Def =:= none, In =/= false, Where =/= c -> + split_optional(Ps, [P|Standard], Opts); +split_optional([_|Ps], Standard, Opts) -> + split_optional(Ps, Standard, Opts); +split_optional([], Standard, Opts) -> + {reverse(Standard), reverse(Opts)}. + +patch_param(P=#param{type=#type{base=Tuple}}, all) when is_tuple(Tuple) -> + P#param{type={class,ignore}}; +patch_param(P=#param{type={merged,_,_,_,_,_,_}}, _) -> + P#param{type={class,ignore}}; +patch_param(P=#param{type=#type{base={class,_}}},_) -> + P#param{type={class,ignore}}; +patch_param(P=#param{type=#type{base={ref,_}}},_) -> + P#param{type={class,ignore}}; +patch_param(P,_) -> P. + +func_arg_name(#param{def=Def}) when Def =/= none -> skip; +func_arg_name(#param{in=false}) -> skip; +func_arg_name(#param{where=c}) -> skip; +func_arg_name(#param{name=Name}) -> + erl_arg_name(Name). + +func_arg(#param{def=Def}) when Def =/= none -> skip; +func_arg(#param{in=false}) -> skip; +func_arg(#param{where=c}) -> skip; +func_arg(#param{name=Name,type=#type{base=string}}) -> + erl_arg_name(Name); +func_arg(#param{name=Name,type=#type{name="wxArrayString"}}) -> + erl_arg_name(Name); +func_arg(#param{name=Name0,type=#type{base={class,_CN}, single=true}}) -> + Name = erl_arg_name(Name0), + "#wx_ref{type=" ++ Name ++ "T,ref=" ++ Name++"Ref}"; +func_arg(#param{name=Name0,type=#type{base={ref,CN}, single=true}}) -> + Name = erl_arg_name(Name0), + "#wx_ref{type=" ++ CN ++ ",ref=" ++ Name++"Ref}"; +func_arg(#param{name=Name0,type={merged,_,#type{base={class,_},single=true},_, + _, #type{base={class,_},single=true},_}}) -> + Name = erl_arg_name(Name0), + "#wx_ref{type=" ++ Name ++ "T,ref=" ++ Name++"Ref}"; +func_arg(#param{name=Name,type=#type{base={enum,_}}}) -> + erl_arg_name(Name); +func_arg(#param{name=Name,type=#type{base={comp,"wxColour",_Tup}, single=true}}) -> + erl_arg_name(Name); +func_arg(#param{name=Name,type=#type{base={comp,"wxDateTime",_Tup}, single=true}}) -> + erl_arg_name(Name); +func_arg(#param{name=Name,type=#type{name="wxArtClient", single=true}}) -> + erl_arg_name(Name); +func_arg(#param{name=Name,type=#type{base={comp,_,Tup}, single=true}}) -> + N = erl_arg_name(Name), + Doc = fun({_,V}) -> erl_arg_name(N)++V end, + "{" ++ args(Doc, ",", Tup) ++ "}"; +func_arg(#param{name=Name}) -> + erl_arg_name(Name). + + +guard_test(#param{type=#type{base={class,_},single=true}}) -> skip; +guard_test(#param{def=Def}) when Def =/= none -> skip; +guard_test(#param{where=c}) -> skip; +guard_test(#param{in=In}) when In == false -> skip; +guard_test(#param{name=N, type=#type{base=string}}) -> + "is_list(" ++ erl_arg_name(N) ++")"; +guard_test(#param{name=N, type=#type{name="wxArtClient"}}) -> + "is_list(" ++ erl_arg_name(N) ++")"; +guard_test(#param{name=N, type=#type{name="wxArrayString"}}) -> + "is_list(" ++ erl_arg_name(N) ++")"; +guard_test(#param{name=Name,type=#type{single=Single}}) + when Single =/= true-> + "is_list(" ++ erl_arg_name(Name) ++ ")"; +guard_test(#param{name=N,type=#type{base=int}}) -> + "is_integer(" ++ erl_arg_name(N) ++ ")"; +guard_test(#param{name=N,type=#type{base=long}}) -> + "is_integer(" ++ erl_arg_name(N) ++ ")"; +guard_test(#param{name=N,type=#type{base=float}}) -> + "is_float(" ++ erl_arg_name(N) ++ ")"; +guard_test(#param{name=N,type=#type{base=double}}) -> + "is_float(" ++ erl_arg_name(N) ++ ")"; +guard_test(#param{name=N,type=#type{base=bool}}) -> + "is_boolean(" ++ erl_arg_name(N) ++ ")"; +guard_test(#param{name=N,type=#type{name="wxDateTime"}}) -> + "tuple_size(" ++ erl_arg_name(N) ++ ") =:= 2"; +guard_test(#param{name=N,type=#type{base=binary}}) -> + "is_binary(" ++ erl_arg_name(N) ++ ")"; +guard_test(#param{name=Name,type=#type{base={enum,_}}}) -> + "is_integer(" ++ erl_arg_name(Name) ++ ")"; +guard_test(#param{name=Name,type=#type{base=eventType}}) -> + "is_atom(" ++ erl_arg_name(Name) ++ ")"; +guard_test(#param{name=_N,type=#type{base={term,_}}}) -> + skip; +guard_test(#param{name=_N,type=#type{base={ref,_}}}) -> + skip; +guard_test(#param{name=_N,type=#type{base={class,_}}}) -> + skip; +guard_test(#param{name=_N,type={merged,_,#type{base={class,_}},_,_,#type{},_}}) -> + skip; +guard_test(#param{name=N,type=#type{base={comp,"wxColour",_Tup}}}) -> + "tuple_size(" ++ erl_arg_name(N) ++ ") =:= 3; tuple_size(" ++ erl_arg_name(N) ++ ") =:= 4"; +guard_test(#param{name=N,type=#type{base={comp,_,Tup}}}) -> + Doc = fun({int,V}) -> "is_integer("++erl_arg_name(N)++V ++")"; + ({double,V}) -> "is_number("++erl_arg_name(N)++V ++")" + end, + args(Doc, ",", Tup); +guard_test(#param{name=N,type={class,ignore}}) -> + "is_record(" ++ erl_arg_name(N)++ ", wx_ref)"; +guard_test(T) -> ?error({unknown_type,T}). + +gen_doc(_Class, [#method{method_type=destructor}]) -> skip; +gen_doc(_Class,[#method{name=N,alias=A,params=Ps,type=T,where=erl_no_opt,method_type=MT}])-> + w("%% @spec (~s~s) -> ~s~n",[doc_arg_types(Ps),"",doc_return_types(T,Ps)]), + w("%% @equiv ", []), + gen_function_clause(erl_func_name(N,A),MT,Ps,empty_list,[no_guards,name_only]); +gen_doc(Class,[#method{name=N,params=Ps,type=T}])-> + {_, Optional} = split_optional(Ps), + NonDef = [Arg || Arg = #param{def=Def,in=In, where=Where} <- Ps, + Def =:= none, In =/= false, Where =/= c], + OptsType = case Optional of + [] -> ""; + _ when NonDef =:= [] -> "[Option]"; + _ -> ", [Option]" + end, + w("%% @spec (~s~s) -> ~s~n", + [doc_arg_types(Ps),OptsType,doc_return_types(T,Ps)]), + doc_optional(Optional, normal), + DocEnum = doc_enum(T,Ps, normal), + case Class of + "utils" -> + w("%% @doc See <a href=\"http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#~s\">" + "external documentation</a>.~n", + [lowercase_all(N)]); + _ -> + w("%% @doc See <a href=\"http://www.wxwidgets.org/manuals/stable/wx_~s.html#~s~s\">" + "external documentation</a>.~n", + [lowercase_all(Class),lowercase_all(Class),lowercase_all(N)]) + end, + doc_enum_desc(DocEnum); +gen_doc(Class, Cs = [#method{name=N, alias=A,method_type=MT}|_]) -> + GetRet = fun(#method{params=Ps,type=T}) -> + doc_return_types(T,Ps) + end, + GetArgs = fun(#method{params=Ps, where=Where}) -> + Opt = case Where of + erl_no_opt -> []; + _ -> + case split_optional(Ps) of + {_, []} -> []; + _ -> ["[Option]"] + end + end, + [doc_arg_type(P) || + P=#param{in=In,def=none,where=W} <- Ps, + In =/= false, W =/= c] ++ Opt + end, + Args = zip(lists:map(GetArgs, Cs)), + Ret = lists:map(GetRet, Cs), + w("%% @spec (~s) -> ~s~n",[args(fun doc_arg/1,",",Args),doc_ret(Ret)]), + case Class of + "utils" -> + w("%% @doc See <a href=\"http://www.wxwidgets.org/manuals/stable/wx_miscellany.html#~s\">" + "external documentation</a>.~n", + [lowercase_all(N)]); + _ -> + w("%% @doc See <a href=\"http://www.wxwidgets.org/manuals/stable/wx_~s.html#~s~s\">" + "external documentation</a>.~n", + [lowercase_all(Class),lowercase_all(Class),lowercase_all(N)]) + end, + Name = case MT of constructor -> "new"; _ -> erl_func_name(N,A) end, + w("%% <br /> Alternatives: ~n",[]), + [gen_doc2(Name, Clause) || Clause <- Cs], + ok. + +gen_doc2(Name,#method{params=Ps,where=erl_no_opt,method_type=MT}) -> + w("%% <p><c>~n",[]), + w("%% ~s(~s) -> ", [Name,doc_arg_types(Ps)]), + gen_function_clause(Name,MT,Ps,empty_list,[no_guards,name_only]), + w(" </c></p>~n",[]); +gen_doc2(Name,#method{params=Ps,type=T}) -> + {NonDef, Optional} = split_optional(Ps), + OptsType = case Optional of + [] -> ""; + _ when NonDef =:= [] -> "[Option]"; + _ -> ", [Option]" + end, + w("%% <p><c>~n",[]), + w("%% ~s(~s~s) -> ~s </c>~n", + [Name,doc_arg_types(Ps),OptsType,doc_return_types(T,Ps)]), + doc_optional(Optional, xhtml), + DocEnum = doc_enum(T,Ps, xhtml), + doc_enum_desc(DocEnum), + w("%% </p>~n",[]). + +doc_arg(ArgList) -> + case all_eq(ArgList) of + true -> hd(ArgList); + false -> + Get = fun(Str) -> + [_Name|Types] = string:tokens(Str, ":"), + case Types of + [Type] -> Type; + _ -> + "term()" + end + end, + Args0 = lists:map(Get, ArgList), + Args = unique(Args0, []), + "X::" ++ args(fun(A) -> A end, "|", Args) + end. + +doc_ret(ArgList) -> + case all_eq(ArgList) of + true -> hd(ArgList); + false -> + args(fun(A) -> A end, "|", ArgList) + end. + +unique([], U) -> reverse(U); +unique([H|R], U) -> + case lists:member(H,U) of + false -> unique(R,[H|U]); + true -> unique(R,U) + end. + +all_eq([H|R]) -> all_eq(R,H). + +all_eq([H|R],H) -> all_eq(R,H); +all_eq([],_) -> true; +all_eq(_,_) -> false. + +zip(List) -> + zip(List, [], [], []). + +zip([[F|L1]|List], Rest, AccL, Acc) -> + zip(List, [L1|Rest], [F|AccL], Acc); +zip(Empty, Rest, AccL, Acc) -> + true = empty(Empty), + case empty(Rest) andalso empty(AccL) of + true -> reverse(Acc); + false -> + zip(reverse(Rest), [], [], [reverse(AccL)|Acc]) + end. + +empty([[]|R]) -> empty(R); +empty([]) -> true; +empty(_) -> false. + +doc_arg_types(Ps0) -> + Ps = [P || P=#param{in=In, where=Where} <- Ps0,In =/= false, Where =/= c], + args(fun doc_arg_type/1, ", ", Ps). +doc_arg_type(#param{name=Name,def=none,type=T}) -> + erl_arg_name(Name) ++ "::" ++ doc_arg_type2(T); +doc_arg_type(#param{name=Name,in=false,type=T}) -> + erl_arg_name(Name) ++ "::" ++ doc_arg_type2(T); +doc_arg_type(_) -> skip. + +doc_arg_type2(T=#type{single=Single}) when Single =:= array; Single =:= list -> + "[" ++ doc_arg_type3(T) ++ "]"; +doc_arg_type2(T) -> + doc_arg_type3(T). + +doc_arg_type3(#type{base=string}) -> "string()"; +doc_arg_type3(#type{name="wxChar", single=S}) when S =/= true -> "string()"; +doc_arg_type3(#type{name="wxArrayString"}) -> "[string()]"; +doc_arg_type3(#type{name="wxDateTime"}) -> "wx:datetime()"; +doc_arg_type3(#type{name="wxArtClient"}) -> "string()"; +doc_arg_type3(#type{base=int}) -> "integer()"; +doc_arg_type3(#type{base=long}) -> "integer()"; +doc_arg_type3(#type{base=bool}) -> "bool()"; +doc_arg_type3(#type{base=float}) -> "float()"; +doc_arg_type3(#type{base=double}) -> "float()"; +doc_arg_type3(#type{base=binary}) -> "binary()"; +doc_arg_type3(#type{base={binary,_}}) -> "binary()"; +doc_arg_type3(#type{base=eventType}) -> "atom()"; +doc_arg_type3(#type{base={ref,N}}) -> N++"()"; +doc_arg_type3(#type{base={term,_N}}) -> "term()"; +doc_arg_type3(T=#type{base={class,N}}) -> + check_class(T), + case get(current_class) of + N -> N ++ "()"; + _ -> N++":" ++ N++"()" + end; +doc_arg_type3({merged,_,T1=#type{base={class,N1}},_,_,T2=#type{base={class,N2}},_}) -> + check_class(T1), + check_class(T2), + Curr = get(current_class), + if + N1 =:= Curr, N2 =:= Curr -> N1++"() | "++ N2++"()"; + N1 =:= Curr -> N1++"() | "++ N2++":" ++ N2++"()"; + N2 =:= Curr -> N1++":" ++ N1++"() | "++ N2++"()"; + true -> + N1++":" ++ N1++"() | "++ N2++":" ++ N2++"()" + end; +doc_arg_type3(#type{base={enum,{_,N}}}) -> uppercase(N); +doc_arg_type3(#type{base={enum,N}}) -> uppercase(N); +doc_arg_type3(#type{base={comp,"wxColour",_Tup}}) -> + "wx:colour()"; +doc_arg_type3(#type{base={comp,_,{record,Name}}}) -> + "wx:" ++ atom_to_list(Name) ++ "()"; +doc_arg_type3(#type{base={comp,_,Tup}}) -> + Doc = fun({int,V}) -> V ++ "::integer()"; + ({double,V}) -> V ++ "::float()" + end, + "{" ++ args(Doc, ",", Tup) ++ "}"; +doc_arg_type3(T) -> ?error({unknown_type,T}). + +doc_return_types(T, Ps) -> + doc_return_types2(T, [P || P=#param{in=In} <- Ps,In =/= true]). +doc_return_types2(void, []) -> "ok"; +doc_return_types2(void, [#param{type=T}]) -> doc_arg_type2(T); +doc_return_types2(T, []) -> doc_arg_type2(T); +doc_return_types2(void, Ps) -> + "{" ++ args(fun doc_arg_type/1,",",Ps) ++ "}"; +doc_return_types2(T, Ps) -> + "{" ++ doc_arg_type2(T) ++ "," ++ args(fun doc_arg_type/1,",",Ps) ++ "}". + +break(xhtml) -> "<br />"; +break(_) -> "". + +doc_optional([],_) -> ok; +doc_optional(Opts,Type) -> + w("%%~s Option = ~s~n", [break(Type),args(fun doc_optional2/1, " | ", Opts)]). + +doc_optional2(#param{name=Name, def=_Def, type=T}) -> + "{" ++ erl_option_name(Name) ++ ", " ++ doc_arg_type2(T) ++ "}". + +doc_enum(#type{base={enum,Enum}},Ps,Break) -> + [doc_enum_type(Enum,Break) | + [doc_enum_type(Type,Break) || #param{type=#type{base={enum,Type}}} <- Ps]]; +doc_enum(_,Ps,Break) -> + [doc_enum_type(Type,Break) || #param{type=#type{base={enum,Type}}} <- Ps]. + +doc_enum_type(Type,Break) -> + {Enum0, #enum{vals=Vals}} = wx_gen:get_enum(Type), + case Enum0 of {_, Enum} -> Enum; Enum -> Enum end, + Consts = get(consts), + Format = fun({Name,_What}) -> + #const{name=Name} = gb_trees:get(Name, Consts), + "?" ++ enum_name(Name) + end, + Vs = args(Format, " | ", Vals), + w("%%~s ~s = integer()~n", [break(Break),uppercase(Enum)]), + {uppercase(Enum),Vs}. + +doc_enum_desc([]) -> ok; +doc_enum_desc([{Enum,Vs}|R]) -> + w("%%<br /> ~s is one of ~s~n", [Enum,Vs]), + doc_enum_desc(R). + +%% Misc functions prefixed with wx +erl_func_name("wx" ++ Name, undefined) -> check_name(lowercase(Name)); +erl_func_name(Name, undefined) -> check_name(lowercase(Name)); +erl_func_name(_, Alias) -> check_name(lowercase(Alias)). + +erl_option_name(Name) -> lowercase(Name). +erl_arg_name(Name) -> uppercase(Name). + +check_name("destroy") -> "'Destroy'"; +check_name("xor") -> "'Xor'"; +check_name("~" ++ _Name) -> "destroy"; +check_name(Name) -> Name. + +marshal_opts([], _,_) -> ""; %% No opts skip this! +marshal_opts(Opts, Align, Args) -> + w(" MOpts = fun", []), + marshal_opts1(Opts,1), + w(";~n (BadOpt, _) -> erlang:error({badoption, BadOpt}) end,~n", []), + w(" BinOpt = list_to_binary(lists:foldl(MOpts, [<<0:32>>], Options)),~n", []), + {Str, _} = align(64, Align, "BinOpt/binary"), + case Args of + [] -> Str; % All Args are optional + _ -> ", " ++ Str + end. + +marshal_opts1([P],N) -> + marshal_opt(P,N); +marshal_opts1([P|R],N) -> + marshal_opt(P,N), + w(";~n ", []), + marshal_opts1(R,N+1). + +marshal_opt(P0=#param{name=Name,type=Type},N) -> + P = P0#param{def=none}, + {Arg,Align} = marshal_arg(Type,erl_arg_name(Name),1), + AStr = if Align =:= 0 -> ""; + Align =:= 1 -> ",0:32" + end, + w("({~s, ~s}, Acc) -> ", [erl_option_name(Name), func_arg(P)]), + arg_type_test(P,"",[]), + case Arg of + skip -> + w("[<<~p:32/?UI~s>>|Acc]", [N, AStr]); + _ -> + w("[<<~p:32/?UI,~s~s>>|Acc]", [N, Arg,AStr]) + end. +marshal_args(Ps) -> + marshal_args(Ps, [], 0). + +marshal_args([#param{where=erl}|Ps], Margs, Align) -> + marshal_args(Ps, Margs, Align); +marshal_args([#param{name=_N,where=c}|Ps], Margs, Align) -> + %% io:format("~p:~p: skip ~p~n",[get(current_class),get(current_func),_N]), + marshal_args(Ps, Margs, Align); +marshal_args([#param{in=false}|Ps], Margs, Align) -> + marshal_args(Ps, Margs, Align); +marshal_args([#param{def=Def}|Ps], Margs, Align) when Def =/= none -> + marshal_args(Ps, Margs, Align); +marshal_args([#param{name=Name, type=Type}|Ps], Margs, Align0) -> + {Arg,Align} = marshal_arg(Type,erl_arg_name(Name),Align0), + marshal_args(Ps, [Arg|Margs], Align); +marshal_args([],Margs, Align) -> + {args(fun(Str) -> Str end, ",", reverse(Margs)), Align}. + +marshal_arg(#type{base={class,_}, single=true}, Name, Align) -> + align(32, Align, Name ++ "Ref:32/?UI"); +marshal_arg({merged,_,#type{base={class,_},single=true},_,_,_,_},Name,Align) -> + align(32, Align, Name ++ "Ref:32/?UI"); +marshal_arg(#type{base={ref,_}, single=true}, Name, Align) -> + align(32, Align, Name ++ "Ref:32/?UI"); +marshal_arg(#type{single=true,base=long}, Name, Align) -> + align(64, Align, Name ++ ":64/?UI"); +marshal_arg(#type{single=true,base=float}, Name, Align) -> + align(32, Align, Name ++ ":32/?F"); +marshal_arg(#type{single=true,base=double}, Name, Align) -> + align(64, Align, Name ++ ":64/?F"); +marshal_arg(#type{single=true,base=int}, Name, Align) -> + align(32, Align, Name ++ ":32/?UI"); +marshal_arg(#type{single=true,base={enum,_Enum}}, Name, Align) -> + align(32, Align, Name ++ ":32/?UI"); + +marshal_arg(#type{single=true,base=bool}, Name, Align) -> + align(32, Align, "(wxe_util:from_bool(" ++ Name ++ ")):32/?UI"); +marshal_arg(#type{name="wxChar", single=Single}, Name, Align0) + when Single =/= true -> + {Str,Align} = + align(32,Align0, "(byte_size("++Name++"_UC)):32/?UI,(" ++ Name ++ "_UC)/binary"), + MsgSize = "(" ++ integer_to_list(Align*4)++"+byte_size("++Name++"_UC))", + {Str++", 0:(((8- (" ++ MsgSize ++" band 16#7)) band 16#7))/unit:8",0}; +marshal_arg(#type{base=string}, Name, Align0) -> + {Str,Align} = + align(32,Align0, "(byte_size("++Name++"_UC)):32/?UI,(" ++ Name ++ "_UC)/binary"), + MsgSize = "(" ++ integer_to_list(Align*4)++"+byte_size("++Name++"_UC))", + {Str++", 0:(((8- (" ++ MsgSize ++" band 16#7)) band 16#7))/unit:8",0}; +marshal_arg(#type{name="wxArrayString"}, Name, Align0) -> + InnerBin = "<<(byte_size(UC_Str)):32/?UI, UC_Str/binary>>", + Outer = "(<< " ++ InnerBin ++ "|| UC_Str <- "++ Name ++"_UCA>>)/binary", + Str0 = "(length("++Name++"_UCA)):32/?UI, " ++ Outer, + {Str,Align} = align(32,Align0,Str0), + MsgSize = "("++integer_to_list(Align*4) ++ + " + lists:sum([byte_size(S)+4||S<-" ++ Name ++"_UCA]))", + AStr = ", 0:(((8- (" ++ MsgSize ++" band 16#7)) band 16#7))/unit:8", + {Str ++ AStr, 0}; +marshal_arg(#type{single=true,base={comp,"wxColour",_Comp}}, Name, Align0) -> + Str = "(wxe_util:colour_bin(" ++ Name ++ ")):16/binary", + {Str,Align0}; +marshal_arg(#type{single=true,base={comp,"wxDateTime",_Comp}}, Name, Align) -> + {"(wxe_util:datetime_bin(" ++ Name ++ ")):24/binary", Align}; +marshal_arg(#type{single=true,base={comp,_,Comp}}, Name, Align0) -> + case hd(Comp) of + {int,_} -> + A = [Name++Spec++":32/?UI" || {int,Spec} <- Comp], + Str = args(fun(Str) -> Str end, ",", A), + {Str,(Align0 + length(Comp)) rem 2}; + {double,_} -> + A = [Name++Spec++":64/float" || {double,Spec} <- Comp], + Str = args(fun(Str) -> Str end, ",", A), + align(64,Align0,Str) + end; +marshal_arg(#type{base={term,_}}, _Name, Align0) -> + {skip,Align0}; +marshal_arg(#type{base=binary}, _Name, Align0) -> + {skip,Align0}; +marshal_arg(#type{base=Base, single=Single}, Name, Align0) + when Single =/= true -> + case Base of + int -> + Str0 = "(length("++Name++")):32/?UI,\n" + " (<< <<C:32/?I>> || C <- "++Name++">>)/binary", + {Str,Align} = align(32,Align0, Str0), + {Str ++ ", 0:((("++integer_to_list(Align)++"+length("++Name++ ")) rem 2)*32)", 0}; + {ObjRef,_} when ObjRef =:= class; ObjRef =:= ref -> + Str0 = "(length("++Name++")):32/?UI,", + Str1 = "\n (<< <<(C#wx_ref.ref):32/?UI>> || C <- "++Name++">>)/binary", + {Str2,Align} = align(32, Align0, Str1), + AlignStr = ", 0:((("++integer_to_list(Align)++"+length("++Name++ ")) rem 2)*32)", + {Str0 ++ Str2 ++ AlignStr, 0}; + {comp, "wxPoint", _} -> + Str0 = "(length("++Name++")):32/?UI,\n" + " (<< <<X:32/?I,Y:32/?I>> || {X,Y} <- "++Name++">>)/binary", + align(32,Align0, Str0); + double -> + Str0 = "(length("++Name++")):32/?UI,\n", + Str1 = " (<< <<C:64/float>> || C <- "++Name++">>)/binary", + {Str,_Align} = align(64,Align0+1, Str1), + {Str0 ++ Str, 0}; + _ -> + ?error({unhandled_array_type, Base}) + end; +marshal_arg(T=#type{name=_wxString}, Name, _Align) -> + ?error({unhandled_type, {Name,T}}). + + +align(32, 0, Str) -> {Str, 1}; +align(32, 1, Str) -> {Str, 0}; +align(64, 0, Str) -> {Str, 0}; +align(64, 1, Str) -> {"0:32," ++ Str,0}; +align(Sz, W, Str) -> align(Sz, W rem 2, Str). + +enum_name(Name) -> + case string:tokens(Name, ":") of + [Name] -> Name; + [C,N] -> C ++ "_" ++ N + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +gen_enums_ints() -> + %% open_write("../include/wx.hrl"), opened in gen_event_recs + w("~n%% Hardcoded Records ~n", []), + w("-record(wxMouseState, {x, y, %% integer() ~n" + " leftDown, middleDown, rightDown, %% bool() ~n" + " controlDown, shiftDown, altDown, metaDown, cmdDown %% bool()~n" + " }).~n", []), + w("-record(wxHtmlLinkInfo, { ~n" + " href, target %% string() ~n" + " }).~n", []), + w("~n%% Hardcoded Defines ~n", []), + Enums = [E || E = {{enum,_},#enum{as_atom=false}} <- get()], + w("-define(wxDefaultSize, {-1,-1}).~n", []), + w("-define(wxDefaultPosition, {-1,-1}).~n", []), + w("~n%% Global Variables ~n", []), + [w("-define(~s, wxe_util:get_const(~s)).~n", [Gvar, Gvar]) || + {Gvar,_,_Id} <- get(gvars)], + w("~n%% Enum and defines ~n", []), + foldl(fun({{enum,Type},Enum= #enum{as_atom=false}}, Done) -> + build_enum_ints(Type,Enum,Done); + (_,Done) -> Done + end, gb_sets:empty(), lists:sort(Enums)), + close(). + +build_enum_ints(Type,#enum{vals=Vals},Done) -> + case Type of + [$@|_] -> ok; % anonymous + {Class,[$@|_]} when Vals =/= [] -> w("% From class ~s ~n", [Class]); + {Class,Enum} when Vals =/= [] -> w("% From ~s::~s ~n", [Class,Enum]); + _ when Vals =/= [] -> w("% Type ~s ~n", [Type]); + _ -> ok + end, + + Format = fun(#const{name=Name,val=Value,is_const=true}) when is_integer(Value) -> + w("-define(~s, ~p).~n", [enum_name(Name),Value]); + (#const{name=Name,val=Value,is_const=false}) when is_integer(Value) -> + w("-define(~s, wxe_util:get_const(~s)).~n", [enum_name(Name),enum_name(Name)]); + (#const{name=Name,val={Str,0}}) -> + case string:tokens(Str, " |()") of + [Token] -> + w("-define(~s, ?~s).~n", [enum_name(Name),Token]); + Tokens -> + Def = args(fun(T) -> [$?|T] end, " bor ", Tokens), + w("-define(~s, (~s)).~n", [enum_name(Name),Def]) + end; + (#const{name=Name,val={Str,N}}) -> + case string:tokens(Str, " |()") of + [Token] -> + w("-define(~s, (?~s+~p)).~n", [enum_name(Name),Token,N]) + end + end, + Consts = get(consts), + Write = fun({Name,_What}, Skip) -> + case gb_sets:is_member(Name,Skip) of + true -> + Skip; + false -> + case gb_trees:lookup(Name, Consts) of + {value, Const} -> + Format(Const), + gb_sets:add(Name,Skip); + none -> Skip + end + end + end, + lists:foldl(Write, Done, Vals). + +gen_event_recs() -> + open_write("../include/wx.hrl"), + erl_copyright(), + w("", []), + w("%% This file is generated DO NOT EDIT~n~n", []), + w("%% All event messages are encapsulated in a wx record ~n" + "%% they contain the widget id and a specialized event record.~n" + "%% Each event record may be sent for one or more event types.~n" + "%% The mapping to wxWidgets is one record per class.~n~n",[]), + w("%% @type wx() = #wx{id=integer(), obj=wx:wxObject(), userData=term(), event=Rec}. Rec is a event record.~n",[]), + w("-record(wx, {id, %% Integer Identity of object.~n" + " obj, %% Object reference that was used in the connect call.~n" + " userData, %% User data specified in the connect call.~n" + " event}).%% The event record ~n~n",[]), + w("%% Here comes the definitions of all event records.~n" + "%% they contain the event type and possible some extra information.~n~n",[]), + Types = [build_event_rec(C) || {_,C=#class{event=Evs}} <- get(), Evs =/= false], + w("%% @type wxEventType() = ~s.~n", + [args(fun(Ev) -> Ev end, " | ", lists:sort(lists:append(Types)))]), + %% close(), closed in gen_enums_ints + ok. + +find_inherited_attr(Param = {PName,_}, Name) -> + #class{parent=Parent, attributes=Attrs} = get({class, Name}), + case lists:keysearch(atom_to_list(PName), #param.name, Attrs) of + {value, P=#param{}} -> + P; + _ -> + find_inherited_attr(Param, Parent) + end. + +filter_attrs(#class{name=Name, parent=Parent,attributes=Attrs}) -> + Attr1 = lists:foldl(fun(#param{acc=skip},Acc) -> Acc; + (P=#param{prot=public},Acc) -> [P|Acc]; + (#param{acc=undefined},Acc) -> Acc; + ({inherited, PName},Acc) -> + case find_inherited_attr(PName, Parent) of + undefined -> + io:format("~p:~p: Missing Event Attr ~p in ~p~n", + [?MODULE,?LINE, PName, Name]), + Acc; + P -> + [P|Acc] + end; + (P, Acc) -> [P|Acc] + end, [], Attrs), + lists:reverse(Attr1). + +build_event_rec(Class=#class{name=Name, event=Evs}) -> + EvTypes = [event_type_name(Ev) || Ev <- Evs], + Str = args(fun(Ev) -> "<em>"++Ev++"</em>" end, ", ", EvTypes), + Attr = filter_attrs(Class), + Rec = event_rec_name(Name), + GetName = fun(#param{name=N}) ->event_attr_name(N) end, + GetType = fun(#param{name=N,type=T}) -> + event_attr_name(N) ++ "=" ++ doc_arg_type2(T) + end, + case Attr =:= [] of + true -> + w("%% @type ~s() = #~s{type=wxEventType()}.~n", [Rec,Rec]), + w("%% <dl><dt>EventType:</dt> <dd>~s</dd></dl>~n",[Str]), +%% case is_command_event(Name) of +%% true -> w("%% This event skips other event handlers.~n",[]); +%% false -> w("%% This event will be handled by other handlers~n",[]) +%% end, + w("%% Callback event: {@link ~s}~n", [Name]), + w("-record(~s, {type}). ~n~n", [Rec]); + false -> + w("%% @type ~s() = #~s{type=wxEventType(),~s}.~n", + [Rec,Rec,args(GetType,",",Attr)]), + w("%% <dl><dt>EventType:</dt> <dd>~s</dd></dl>~n",[Str]), +%% case is_command_event(Name) of +%% true -> w("%% This event skips other event handlers.~n",[]); +%% false -> w("%% This event will be handled by other handlers~n",[]) +%% end, + w("%% Callback event: {@link ~s}~n", [Name]), + w("-record(~s,{type, ~s}). ~n~n", [Rec,args(GetName,",",Attr)]) + end, + EvTypes. + +is_command_event(Name) -> + case lists:member("wxCommandEvent", parents(Name)) of + true -> true; + false -> false + end. + +event_rec_name(Name0 = "wx" ++ _) -> + "tnevE" ++ Name1 = reverse(Name0), + reverse(Name1). + +event_type_name({EvN,_,_}) -> event_type_name(EvN); +event_type_name({EvN,_}) -> event_type_name(EvN); +event_type_name(EvN) -> + "wxEVT_" ++ Ev = atom_to_list(EvN), + lowercase_all(Ev). + +event_attr_name("m_" ++ Attr) -> + lowercase(Attr); +event_attr_name(Attr) -> + lowercase(Attr). + + +gen_funcnames() -> + open_write("../src/gen/wxe_debug.hrl"), + erl_copyright(), + w("%% This file is generated DO NOT EDIT~n~n", []), + w("wxdebug_table() -> ~n[~n", []), + w(" {0, {wx, internal_batch_start, 0}},~n", []), + w(" {1, {wx, internal_batch_end, 0}},~n", []), + w(" {4, {wxObject, internal_destroy, 1}},~n", []), + Ns = get_unique_names(), + [w(" {~p, {~s, ~s, ~p}},~n", [Id,Class,erl_func_name(Name,undefined),A]) || {Class,Name,A,Id} <- Ns], + w(" {-1, {mod, func, -1}}~n",[]), + w("].~n~n", []), + close(), + open_write("../src/gen/wxe_funcs.hrl"), + erl_copyright(), + w("%% This file is generated DO NOT EDIT~n~n", []), + w("%% We define each id so we don't get huge diffs when adding new funcs/classes~n~n",[]), + [w("-define(~s_~s, ~p).~n", [Class,Name,Id]) || {Class,Name,_,Id} <- Ns], + close(). + +get_unique_name(ID) when is_integer(ID) -> + Tree = get(unique_names), + {Class,Name, _,_} = gb_trees:get(ID, Tree), + Class ++ "_" ++ Name. + +get_unique_names() -> + Tree = get(unique_names), + gb_trees:values(Tree). + +gen_unique_names(Defs) -> + Names = [ unique_names(Ms, Class) || #class{name=Class, methods=Ms} <- Defs], + Data = [{Id, Struct} || Struct = {_,_,_,Id} <- lists:append(Names)], + Tree = gb_trees:from_orddict(lists:sort(Data)), + put(unique_names, Tree). + +unique_names(Ms0, Class) -> + Ms1 = [M || M = #method{where = W} <- lists:append(Ms0), + W =/= erl_no_opt], + Ms2 = lists:keysort(#method.name, Ms1), + Ms = split_list(fun(#method{name=N}, M) -> {N =:= M, N} end, undefined, Ms2), + unique_names2(Ms,Class). +%% by Names +unique_names2([[#method{id=Id, name=Method,alias=Alias, max_arity=A}]|Ms], Class) -> + [{Class,uname(alias(Method,Alias),Class),A,Id} | unique_names2(Ms,Class)]; +unique_names2([Ms0|RMs], Class) -> + Split = fun(#method{max_arity=A}, P) -> {A =:= P, A} end, + Ms = split_list(Split, 0, Ms0), + unique_names3(Ms, Class) ++ unique_names2(RMs, Class); +unique_names2([], _Class) -> []. +%% by Arity +unique_names3([[#method{id=Id, name=Method,alias=Alias, max_arity=A}]|Ms], Class) -> + [{Class,uname(alias(Method,Alias),Class) ++ "_" ++ integer_to_list(A),A,Id} | unique_names3(Ms,Class)]; +unique_names3([Ms0|RMs], Class) -> + unique_names4(Ms0, 0, Class) ++ unique_names3(RMs, Class); +unique_names3([], _Class) -> []. + +unique_names4([#method{id=Id, name=Method,alias=Alias, max_arity=A}|Ms], C, Class) -> + [{Class,uname(alias(Method,Alias),Class) ++ "_" ++ integer_to_list(A) ++ "_" ++ integer_to_list(C),A,Id} + | unique_names4(Ms,C+1,Class)]; +unique_names4([], _, _Class) -> []. + +alias(Method, undefined) -> Method; +alias(_, Alias) -> Alias. + +uname(Class,Class) -> "new"; +uname([$~ | _], _ ) -> "destruct"; +uname(Name, _) -> Name. + +split_list(F, Keep, List) -> + split_list(F, Keep, List, []). + +split_list(F, Keep, [M|Ms], Acc) -> + case F(M,Keep) of + {true, Test} -> + split_list(F, Test, Ms, [M|Acc]); + {false, Test} when Acc =:= [] -> + split_list(F, Test, Ms, [M]); + {false, Test} -> + [lists:reverse(Acc)|split_list(F, Test, Ms, [M])] + end; +split_list(_, _, [], []) -> []; +split_list(_, _, [], Acc) -> [lists:reverse(Acc)]. + + diff --git a/lib/wx/api_gen/wx_xml/.gitignore b/lib/wx/api_gen/wx_xml/.gitignore new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/lib/wx/api_gen/wx_xml/.gitignore diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf new file mode 100644 index 0000000000..df154f0125 --- /dev/null +++ b/lib/wx/api_gen/wxapi.conf @@ -0,0 +1,1777 @@ +%% -*- erlang -*- +%% +%% %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% +% +%% Api defs file, defines the classes and members we want. + +%% {class,wxObject,Options,[Function|{Func,Opt}]}. +%% {enum, Type, SkipPart} + +{const_skip, [wxGenericFindReplaceDialog]}. +{not_const, [wxHAS_INT64,wxBYTE_ORDER,wxRETAINED, + wxFONTENCODING_UTF32,wxFONTENCODING_UTF16, + wxDEFAULT_CONTROL_BORDER,wxMOD_CMD, + wxMAJOR_VERSION, wxMINOR_VERSION, + wxRELEASE_NUMBER,wxSUBRELEASE_NUMBER,wxBETA_NUMBER + ]}. + +{gvars, + [ + {wxITALIC_FONT, wxFont}, + {wxNORMAL_FONT, wxFont}, + {wxSMALL_FONT, wxFont}, + {wxSWISS_FONT, wxFont}, + + {wxBLACK_DASHED_PEN, wxPen}, + {wxBLACK_PEN, wxPen}, + {wxCYAN_PEN, wxPen}, + {wxGREEN_PEN, wxPen}, + {wxGREY_PEN, wxPen}, + {wxLIGHT_GREY_PEN, wxPen}, + {wxMEDIUM_GREY_PEN, wxPen}, + {wxRED_PEN, wxPen}, + {wxTRANSPARENT_PEN, wxPen}, + {wxWHITE_PEN, wxPen}, + + {wxBLACK_BRUSH, wxBrush}, + {wxBLUE_BRUSH, wxBrush}, + {wxCYAN_BRUSH, wxBrush}, + {wxGREEN_BRUSH, wxBrush}, + {wxGREY_BRUSH, wxBrush}, + {wxLIGHT_GREY_BRUSH, wxBrush}, + {wxMEDIUM_GREY_BRUSH, wxBrush}, + {wxRED_BRUSH, wxBrush}, + {wxTRANSPARENT_BRUSH, wxBrush}, + {wxWHITE_BRUSH, wxBrush}, + + {wxCROSS_CURSOR, wxCursor}, + {wxHOURGLASS_CURSOR, wxCursor}, + {wxSTANDARD_CURSOR, wxCursor}, + + {wxBLACK, wxColour}, + {wxBLUE, wxColour}, + {wxCYAN, wxColour}, + {wxGREEN, wxColour}, + {wxLIGHT_GREY, wxColour}, + {wxRED, wxColour}, + {wxWHITE, wxColour}, + + {wxNullBitmap, {address,wxBitmap}}, + {wxNullIcon, {address,wxIcon}}, + {wxNullCursor, {address,wxCursor}}, + {wxNullPen, {address,wxPen}}, + {wxNullBrush, {address,wxBrush}}, + {wxNullPalette, {address,wxPalette}}, + {wxNullFont, {address,wxFont}}]}. +{enum, wxBackgroundStyle, "wxBG_STYLE_"}. +{enum, wxWindowVariant, "wxWINDOW_VARIANT_"}. +{enum, wxBitmapType, "wxBITMAP_TYPE_"}. + +{class, wxeEvtHandler, object, [taylormade, {alias, [{wxeEvtHandler, wxEvtHandler}]}], + [{'Connect', [{"eventType",{base,eventType}},{"userData",nowhere}]}, + {'Disconnect',[{"eventType",{base,eventType}},{"userData",nowhere}]}] +}. + +{class, wxWindowGTK, wxEvtHandler, + [{alias, [{wxWindowGTK, wxWindow}]}], + [wxWindow,'~wxWindow', %% 'AddChild', + 'CacheBestSize','CaptureMouse', + 'Center','CenterOnParent','Centre','CentreOnParent','ClearBackground', + {'ClientToScreen',[{"x",both},{"y",both}]}, 'Close', + 'ConvertDialogToPixels','ConvertPixelsToDialog','Destroy','DestroyChildren', + 'Disable',%%'DoGetBestSize','DoUpdateWindowUI', 'DragAcceptFiles', + 'Enable', + 'FindFocus','FindWindow','FindWindowById','FindWindowByName','FindWindowByLabel', + 'Fit','FitInside','Freeze', 'GetAcceleratorTable', % 'GetAccessible', + 'GetBackgroundColour','GetBackgroundStyle', + 'GetBestSize','GetCaret','GetCapture','GetCharHeight', + 'GetCharWidth','GetChildren', + %%'GetClassDefaultAttributes','GetConstraints' + 'GetClientSize','GetContainingSizer','GetCursor', + %%'GetDefaultAttributes', + 'GetDropTarget','GetEventHandler','GetExtraStyle','GetFont','GetForegroundColour', + 'GetGrandParent', + {'GetHandle', [{return, [{type,"wxUIntPtr"}, {ref,pointer}, {base, int}]}]}, + 'GetHelpText','GetId','GetLabel','GetMaxSize', + 'GetMinSize','GetName','GetParent','GetPosition','GetRect', + {'GetScreenPosition', [{"x",out},{"y",out}]}, 'GetScreenRect', + 'GetScrollPos','GetScrollRange','GetScrollThumb','GetSize','GetSizer', + {'GetTextExtent', [{"descent", out}, {"externalLeading", out}]}, + 'GetToolTip','GetUpdateRegion',%'GetValidator', + 'GetVirtualSize','GetWindowStyleFlag','GetWindowVariant','HasCapture','HasScrollbar', + 'HasTransparentBackground','Hide','InheritAttributes','InitDialog', + 'InvalidateBestSize','IsEnabled','IsExposed','IsRetained','IsShown','IsTopLevel', + 'Layout','LineDown','LineUp','Lower','MakeModal','Move','MoveAfterInTabOrder', + 'MoveBeforeInTabOrder','Navigate',%'OnInternalIdle', + 'PageDown','PageUp', + 'PopEventHandler','PopupMenu',%'PushEventHandler', + 'Raise', 'Refresh', 'RefreshRect',%'RegisterHotKey', + 'ReleaseMouse','RemoveChild',%'RemoveEventHandler', + 'Reparent', + 'ScreenToClient','ScrollLines','ScrollPages','ScrollWindow','SetAcceleratorTable', + %%'SetAccessible', + 'SetAutoLayout','SetBackgroundColour','SetBackgroundStyle', + 'SetCaret','SetClientSize','SetContainingSizer','SetCursor', + %%'SetConstraints','SetInitialBestSize', + 'SetMaxSize','SetMinSize', + 'SetOwnBackgroundColour','SetOwnFont','SetOwnForegroundColour','SetDropTarget', + %%'SetEventHandler', + 'SetExtraStyle','SetFocus','SetFocusFromKbd','SetFont', + 'SetForegroundColour','SetHelpText','SetId','SetLabel','SetName','SetPalette', + 'SetScrollbar','SetScrollPos','SetSize','SetSizeHints','SetSizer','SetSizerAndFit', + 'SetThemeEnabled','SetToolTip',%'SetValidator', + 'SetVirtualSize', + 'SetVirtualSizeHints','SetWindowStyle','SetWindowStyleFlag','SetWindowVariant', + 'ShouldInheritColours','Show','Thaw','TransferDataFromWindow', + 'TransferDataToWindow',%'UnregisterHotKey', + 'Update','UpdateWindowUI','Validate', + 'WarpPointer']}. + +{class, wxTopLevelWindowGTK, wxWindow, + [{alias, [{wxTopLevelWindowGTK, wxTopLevelWindow}]}], + ['GetIcon','GetIcons','GetTitle','IsActive','Iconize', + 'IsFullScreen','IsIconized','IsMaximized','Maximize', + 'RequestUserAttention','SetIcon','SetIcons', + 'CenterOnScreen', 'CentreOnScreen', + %%'SetLeftMenu', 'SetRightMenu', + 'SetShape','SetTitle','ShowFullScreen' + ]}. + +{class, wxFrame, wxTopLevelWindow, [], + ['wxFrame','~wxFrame',%'Centre', + 'Create','CreateStatusBar','CreateToolBar', + 'GetClientAreaOrigin','GetMenuBar','GetStatusBar','GetStatusBarPane', + 'GetToolBar',%'OnCreateStatusBar','OnCreateToolBar', + 'ProcessCommand','SendSizeEvent','SetMenuBar','SetStatusBar', + 'SetStatusBarPane','SetStatusText', + {'SetStatusWidths', [{"n",{c_only,{length,"widths_field"}}}]}, + 'SetToolBar']}. + +{class, wxMiniFrame, wxFrame, [], + ['wxMiniFrame','~wxMiniFrame','Create']}. + +%% Hmm what do we do with these +%% {class, wxValidator, root,[], +%% ['wxValidator','~wxValidator','Clone','GetWindow','SetBellOnError','SetWindow', +%% 'TransferFromWindow','TransferToWindow','Validate']}. +%% {class, wxGenericValidator, wxValidator,[], +%% ['wxGenericValidator','~wxGenericValidator','Clone', +%% 'TransferFromWindow','TransferToWindow']}. +%% {class, wxTextValidator, wxValidator,[], +%% ['wxTextValidator','Clone','GetExcludes','GetIncludes','GetStyle', +%% 'OnChar','SetExcludes','SetIncludes','SetStyle','TransferFromWindow', +%% 'TransferToWindow','Validate']}. + +{class, wxSplashScreen, wxFrame, [], + ['wxSplashScreen','~wxSplashScreen',%'OnCloseWindow', + 'GetSplashStyle', %'GetSplashWindow', + 'GetTimeout']}. + +{class, wxPanel, wxWindow, [], + ['wxPanel','~wxPanel',%'Create', + %%'GetDefaultItem', + 'InitDialog'%, + %%'OnSysColourChanged', %'SetDefaultItem','SetFocus','SetFocusIgnoringChildren' + ]}. + +{class, wxScrolledWindow, wxPanel, [], + ['wxScrolledWindow','~wxScrolledWindow', + 'CalcScrolledPosition','CalcUnscrolledPosition',%'Create', + 'EnableScrolling','GetScrollPixelsPerUnit','GetViewStart', + %%'GetVirtualSize','IsRetained', + 'DoPrepareDC',%'OnDraw', + 'PrepareDC','Scroll','SetScrollbars', + 'SetScrollRate',{'SetTargetWindow',[{"pushEventHandler", nowhere}]}]}. + +{class, wxSashWindow, wxWindow, [], + ['wxSashWindow','~wxSashWindow','GetSashVisible','GetMaximumSizeX', + 'GetMaximumSizeY','GetMinimumSizeX','GetMinimumSizeY', + 'SetMaximumSizeX','SetMaximumSizeY','SetMinimumSizeX','SetMinimumSizeY', + 'SetSashVisible' %% ,'HasBorder', 'SetSashBorder' 2.6 only + ]}. + +{class, wxSashLayoutWindow, wxSashWindow, [], + ['wxSashLayoutWindow','Create','GetAlignment','GetOrientation', + %% 'OnCalculateLayout','OnQueryLayoutInfo', Requires events for overloading ? + 'SetAlignment','SetDefaultSize','SetOrientation' + ]}. + +{enum, {"wxGrid","wxGridSelectionModes"}, "wxGrid::wxGrid"}. +{class, wxGrid, wxScrolledWindow, [], + ['wxGrid','~wxGrid','AppendCols','AppendRows','AutoSize',%'AutoSizeColOrRow', + 'AutoSizeColumn','AutoSizeColumns','AutoSizeRow','AutoSizeRows','BeginBatch', + 'BlockToDeviceRect','CanDragColSize','CanDragRowSize','CanDragGridSize', + 'CanEnableCellControl',%'CanHaveAttributes', + 'CellToRect','ClearGrid','ClearSelection','CreateGrid', + 'DeleteCols','DeleteRows','DisableCellEditControl', + 'DisableDragColSize','DisableDragGridSize','DisableDragRowSize', + 'EnableCellEditControl','EnableDragColSize','EnableDragGridSize', + 'EnableDragRowSize','EnableEditing','EnableGridLines','EndBatch','Fit', + 'ForceRefresh','GetBatchCount','GetCellAlignment','GetCellBackgroundColour', + 'GetCellEditor','GetCellFont','GetCellRenderer','GetCellTextColour','GetCellValue', + %'GetColLeft', + 'GetColLabelAlignment','GetColLabelSize','GetColLabelValue', + 'GetColMinimalAcceptableWidth',%'GetColMinimalWidth', + %'GetColRight','GetColSize', + 'GetDefaultCellAlignment','GetDefaultCellBackgroundColour','GetDefaultCellFont', + 'GetDefaultCellTextColour','GetDefaultColLabelSize','GetDefaultColSize', + 'GetDefaultEditor','GetDefaultEditorForCell','GetDefaultEditorForType', + 'GetDefaultRenderer','GetDefaultRendererForCell','GetDefaultRendererForType', + 'GetDefaultRowLabelSize','GetDefaultRowSize','GetGridCursorCol','GetGridCursorRow', + 'GetGridLineColour','GridLinesEnabled','GetLabelBackgroundColour','GetLabelFont', + 'GetLabelTextColour','GetNumberCols','GetNumberRows','GetOrCreateCellAttr', + 'GetRowMinimalAcceptableHeight',%'GetRowMinimalHeight', + 'GetRowLabelAlignment', + 'GetRowLabelSize','GetRowLabelValue','GetRowSize','GetScrollLineX','GetScrollLineY', + %'GetSelectionMode', + 'GetSelectedCells','GetSelectedCols','GetSelectedRows', + 'GetSelectionBackground','GetSelectionBlockTopLeft','GetSelectionBlockBottomRight', + 'GetSelectionForeground',%'GetTable', + 'GetViewWidth', + 'GetGridWindow', 'GetGridRowLabelWindow', + 'GetGridColLabelWindow', 'GetGridCornerLabelWindow', + 'HideCellEditControl', + %'InitColWidths','InitRowHeights', + 'InsertCols','InsertRows', + 'IsCellEditControlEnabled','IsCurrentCellReadOnly','IsEditable','IsInSelection', + 'IsReadOnly','IsSelection','IsVisible','MakeCellVisible','MoveCursorDown', + 'MoveCursorLeft','MoveCursorRight','MoveCursorUp','MoveCursorDownBlock', + 'MoveCursorLeftBlock','MoveCursorRightBlock','MoveCursorUpBlock','MovePageDown', + 'MovePageUp','RegisterDataType','SaveEditControlValue','SelectAll','SelectBlock', + 'SelectCol', %'SelectionToDeviceRect', + 'SelectRow','SetCellAlignment', + 'SetCellBackgroundColour','SetCellEditor','SetCellFont','SetCellRenderer', + 'SetCellTextColour','SetCellValue','SetColAttr','SetColFormatBool', + 'SetColFormatNumber','SetColFormatFloat','SetColFormatCustom', + 'SetColLabelAlignment','SetColLabelSize','SetColLabelValue','SetColMinimalWidth', + 'SetColMinimalAcceptableWidth','SetColSize','SetDefaultCellAlignment', + 'SetDefaultCellBackgroundColour','SetDefaultCellFont','SetDefaultCellTextColour', + 'SetDefaultEditor','SetDefaultRenderer','SetDefaultColSize','SetDefaultRowSize', + 'SetGridCursor','SetGridLineColour','SetLabelBackgroundColour','SetLabelFont', + 'SetLabelTextColour','SetMargins',%'SetOrCalcColumnSizes','SetOrCalcRowSizes', + 'SetReadOnly','SetRowAttr','SetRowLabelAlignment','SetRowLabelSize', + 'SetRowLabelValue','SetRowMinimalHeight','SetRowMinimalAcceptableHeight', + 'SetRowSize','SetScrollLineX','SetScrollLineY','SetSelectionBackground', + 'SetSelectionForeground','SetSelectionMode',%'SetTable', + 'ShowCellEditControl','XToCol','XToEdgeOfCol','YToEdgeOfRow','YToRow']}. + +{class, wxGridCellRenderer, root, [], + ['Draw','GetBestSize']}. +{class, wxGridCellEditor, root, [], + ['Create', + 'IsCreated', 'SetSize', 'Show', + 'PaintBackground', 'BeginEdit', 'EndEdit', 'Reset', 'StartingKey', + 'StartingClick', 'HandleReturn' + %'Destroy','Clone','~wxGridCellEditor', + ]}. + +{class, wxGridCellBoolRenderer, wxGridCellRenderer, [], + ['wxGridCellBoolRenderer']}. +{class, wxGridCellBoolEditor, wxGridCellEditor, [], + ['wxGridCellBoolEditor', 'IsTrueValue', 'UseStringValues']}. + +{class, wxGridCellFloatRenderer, wxGridCellStringRenderer, [], + ['wxGridCellFloatRenderer', 'GetPrecision', 'GetWidth', + 'SetParameters', 'SetPrecision', 'SetWidth']}. +{class, wxGridCellFloatEditor, wxGridCellEditor, [], + ['wxGridCellFloatEditor', 'SetParameters' ]}. + +{class, wxGridCellStringRenderer, wxGridCellRenderer, [], ['wxGridCellStringRenderer']}. +{class, wxGridCellTextEditor, wxGridCellEditor, [], + ['wxGridCellTextEditor','SetParameters']}. +{class, wxGridCellChoiceEditor, wxGridCellEditor, [{skip, [{'wxGridCellChoiceEditor', 3}]}], + ['wxGridCellChoiceEditor','SetParameters']}. + +{class, wxGridCellNumberRenderer, wxGridCellStringRenderer, [], + ['wxGridCellNumberRenderer']}. +{class, wxGridCellNumberEditor, wxGridCellTextEditor, [], + ['wxGridCellNumberEditor','GetValue','SetParameters']}. + +{class, wxGridCellAttr, root, [], + [%'wxGridCellAttr','Clone','IncRef','DecRef', + 'SetTextColour','SetBackgroundColour','SetFont','SetAlignment','SetReadOnly', + 'SetRenderer','SetEditor','HasTextColour','HasBackgroundColour','HasFont', + 'HasAlignment','HasRenderer','HasEditor','GetTextColour','GetBackgroundColour', + 'GetFont','GetAlignment','GetRenderer','GetEditor','IsReadOnly','SetDefAttr']}. + +{enum, wxDirection, "wx"}. +{enum, wxLayoutDirection, "wxLayout_"}. + +{class, wxDC, object, + [{skip, [{'DrawEllipse',5},{'DrawRectangle',5}, + {'DrawRoundedRectangle',6},{'SetClippingRegion',5}]}], + [{'Blit',7},'CalcBoundingBox','Clear','ComputeScaleAndOrigin',{'CrossHair',1}, + 'DestroyClippingRegion','DeviceToLogicalX','DeviceToLogicalXRel', + 'DeviceToLogicalY','DeviceToLogicalYRel',{'DrawArc',3},{'DrawBitmap',3}, + {'DrawCheckMark',1},{'DrawCircle',2},'DrawEllipse',{'DrawEllipticArc',4}, + {'DrawIcon',2},{'DrawLabel',4},{'DrawLine',2}, + {'DrawLines', [{"n",{c_only,{length,"points"}}}]}, + {'DrawPolygon', [{"n",{c_only,{length,"points"}}}]}, %'DrawPolyPolygon', + {'DrawPoint',1},'DrawRectangle', + {'DrawRotatedText',3}, 'DrawRoundedRectangle',%'DrawSpline', + {'DrawText',2}, + 'EndDoc','EndPage',{'FloodFill',3},'GetBackground','GetBackgroundMode', + 'GetBrush','GetCharHeight','GetCharWidth',{'GetClippingBox',1},'GetFont', + 'GetLayoutDirection','GetLogicalFunction','GetMapMode','GetMultiLineTextExtent', + 'GetPartialTextExtents','GetPen',{'GetPixel',2},'GetPPI','GetSize','GetSizeMM', + 'GetTextBackground','GetTextExtent','GetTextForeground', + 'GetUserScale','GradientFillConcentric','GradientFillLinear', + 'LogicalToDeviceX','LogicalToDeviceXRel','LogicalToDeviceY','LogicalToDeviceYRel', + 'MaxX','MaxY','MinX','MinY','IsOk','ResetBoundingBox','SetAxisOrientation', + 'SetBackground','SetBackgroundMode','SetBrush','SetClippingRegion','SetDeviceOrigin', + 'SetFont','SetLayoutDirection','SetLogicalFunction','SetMapMode', 'SetPalette', + 'SetPen','SetTextBackground','SetTextForeground','SetUserScale','StartDoc','StartPage']}. + +{class,wxMirrorDC, wxDC, [], ['wxMirrorDC', '~wxMirrorDC']}. +{class,wxScreenDC, wxDC, [], ['wxScreenDC', '~wxScreenDC']}. +{class,wxPostScriptDC,wxDC,[],['wxPostScriptDC','~wxPostScriptDC','SetResolution','GetResolution']}. +{class,wxWindowDC, wxDC, [], ['wxWindowDC', '~wxWindowDC']}. +{class,wxClientDC,wxWindowDC,[],['wxClientDC', '~wxClientDC']}. +{class,wxPaintDC, wxWindowDC, [], ['wxPaintDC', '~wxPaintDC']}. +%%{class,wxPrinterDC, wxDC, [], ['wxPrinterDC','GetPaperRect']}. Not in GTK +{class,wxMemoryDC, wxDC, [], ['wxMemoryDC', '~wxMemoryDC','SelectObject','SelectObjectAsSource']}. +{class,wxBufferedDC,wxMemoryDC,[],['wxBufferedDC','~wxBufferedDC','Init']}. +{class,wxBufferedPaintDC,wxBufferedDC,[],['wxBufferedPaintDC', '~wxBufferedPaintDC']}. +%% Only a typedef! +%%{class,wxAutoBufferedPaintDC,wxBufferedPaintDC,[],['wxAutoBufferedPaintDC']}. + +{class, wxGraphicsObject, object, [{ifdef, wxUSE_GRAPHICS_CONTEXT}], + ['GetRenderer','IsNull']}. +{class, wxGraphicsContext, wxGraphicsObject, [{ifdef, wxUSE_GRAPHICS_CONTEXT}], + ['Create', %%CreateFromNative CreateFromNativeWindow + 'CreatePen','CreateBrush','CreateRadialGradientBrush', + 'CreateLinearGradientBrush','CreateFont','CreateMatrix', + 'CreatePath','Clip','ResetClip', + 'DrawBitmap','DrawEllipse','DrawIcon','DrawLines','DrawPath', + 'DrawRectangle','DrawRoundedRectangle','DrawText','FillPath', + 'StrokePath','GetNativeContext','GetPartialTextExtents', + 'GetTextExtent','Rotate','Scale','Translate', + 'GetTransform','SetTransform','ConcatTransform', + 'SetBrush','SetFont','SetPen','StrokeLine','StrokeLines']}. +{class, wxGraphicsMatrix, wxGraphicsObject, [{ifdef, wxUSE_GRAPHICS_CONTEXT}], + ['Concat','Get','GetNativeMatrix','Invert','IsEqual','IsIdentity', + 'Rotate','Scale','Translate','Set','TransformPoint','TransformDistance']}. +{class, wxGraphicsPath, wxGraphicsObject, [{ifdef, wxUSE_GRAPHICS_CONTEXT}], + ['MoveToPoint','AddArc','AddArcToPoint','AddCircle','AddCurveToPoint', + 'AddEllipse','AddLineToPoint','AddPath','AddQuadCurveToPoint', + 'AddRectangle','AddRoundedRectangle','CloseSubpath','Contains', + 'GetBox','GetCurrentPoint','Transform' + %'GetNativePath','UnGetNativePath' + ]}. +{class, wxGraphicsRenderer, object, [{ifdef, wxUSE_GRAPHICS_CONTEXT}], + ['GetDefaultRenderer','CreateContext', + %%'CreateContextFromNativeContext', 'CreateContextFromNativeWindow', + 'CreatePen','CreateBrush', + 'CreateLinearGradientBrush','CreateRadialGradientBrush','CreateFont', + 'CreateMatrix','CreatePath']}. + +{class, wxGraphicsPen, wxGraphicsObject,[{ifdef, wxUSE_GRAPHICS_CONTEXT}], []}. +{class, wxGraphicsBrush,wxGraphicsObject,[{ifdef, wxUSE_GRAPHICS_CONTEXT}], []}. +{class, wxGraphicsFont, wxGraphicsObject,[{ifdef, wxUSE_GRAPHICS_CONTEXT}], []}. + +{class, wxMenuBar, wxWindow, [{skip, [{wxMenuBar,4}]}], + [ + 'wxMenuBar','~wxMenuBar','Append','Check','Enable','EnableTop', + 'FindMenu', 'FindMenuItem',{'FindItem', [{"menu",skip}]},'GetHelpString', + 'GetLabel','GetLabelTop','GetMenu','GetMenuCount','Insert','IsChecked', + 'IsEnabled',%'Refresh', + 'Remove','Replace','SetHelpString', + 'SetLabel','SetLabelTop']}. + +{class, wxControl, wxWindow, [], [% 'Command','GetLabelText', + 'GetLabel','SetLabel']}. + +{class, wxControlWithItems, wxControl, + [{skip, [{'GetClientObject',1},{'SetClientObject',2}]}], + [ + {'Append',[{"clientData",[{skip_member, void}]}, + {"strings", [{erl_func, "appendStrings"}]}]}, + 'Clear','Delete','FindString', + %% 'GetClientData','SetClientData', + {'GetClientObject', [{"n", [{erl_func, "getClientData"}]}]}, + {'SetClientObject', [{"n", [{erl_func, "setClientData"}]}]}, + 'GetCount','GetSelection','GetString','GetStringSelection', + {'Insert',[{"clientData",[{skip_member, void}]}]},%'Number', + 'IsEmpty','Select','SetSelection','SetString','SetStringSelection' + ]}. + +{enum, wxItemKind, "wxITEM_"}. + +{class, wxMenu, wxEvtHandler, [], + ['wxMenu','~wxMenu',{'Append', [{"text",{def,none}}]}, + 'AppendCheckItem','AppendRadioItem', + 'AppendSeparator','Break','Check','Delete','Destroy','Enable', + {'FindItem', [{"menu",skip}]},'FindItemByPosition','GetHelpString','GetLabel', + 'GetMenuItemCount','GetMenuItems','GetTitle','Insert', + 'InsertCheckItem','InsertRadioItem','InsertSeparator','IsChecked', + 'IsEnabled','Prepend','PrependCheckItem','PrependRadioItem', + 'PrependSeparator','Remove','SetHelpString','SetLabel','SetTitle']}. + +{class, wxMenuItem, object, [], + [{'wxMenuItem',[{"isCheckable",skip_member}]}, + '~wxMenuItem','Check','Enable', + %%'GetBackgroundColour', + 'GetBitmap', %%'GetFont', + 'GetHelp','GetId','GetKind','GetLabel','GetLabelFromText', + %%'GetMarginWidth','GetTextColour', + 'GetMenu',%'GetName', class clash will not compile on windows + 'GetText', + 'GetSubMenu','IsCheckable','IsChecked','IsEnabled', + 'IsSeparator','IsSubMenu', + %%'SetBackgroundColour', + 'SetBitmap', %%'SetBitmaps',%%'SetFont', + 'SetHelp','SetMenu','SetSubMenu','SetText' + %%'SetTextColour',%'SetMarginWidth' + ]}. + +{class, wxToolBar, wxControl, [], + ['AddControl','AddSeparator','AddTool','AddCheckTool','AddRadioTool', + 'DeleteTool','DeleteToolByPos','EnableTool','FindById','FindControl', + 'FindToolForPosition','GetToolSize','GetToolBitmapSize','GetMargins', + %%'GetToolClientData' , %%'SetToolClientData', + 'GetToolEnabled','GetToolLongHelp','GetToolPacking', + 'GetToolPos','GetToolSeparation','GetToolShortHelp','GetToolState', + 'InsertControl','InsertSeparator','InsertTool', + %%'OnLeftClick','OnMouseEnter','OnRightClick', + 'Realize','RemoveTool', %'SetBitmapResource', + {'SetMargins',2},'SetToolBitmapSize', + 'SetToolLongHelp', + 'SetToolPacking','SetToolShortHelp','SetToolSeparation','ToggleTool' + ]}. + +{class, wxStatusBarGeneric, wxWindow, + [{alias, [{wxStatusBarGeneric, wxStatusBar}]}], + [{'wxStatusBar',[{"size", skip_member}]}, + '~wxStatusBar', + {'Create',[{"size", skip_member}]}, + 'GetFieldRect','GetFieldsCount','GetStatusText','PopStatusText', + 'PushStatusText', + {'SetFieldsCount', [{"number", {def,none}}, + {"widths", [{single, array}, {def, "(int *) NULL"}]}]}, + 'SetMinHeight','SetStatusText', + {'SetStatusWidths', [{"n",{c_only,{length,"widths_field"}}}]}, + {'SetStatusStyles', [{"n",{c_only,{length,"styles"}}}]} + ]}. + +{class, wxBitmap, object,[], + [{'wxBitmap',[{"bits",[in,{base,binary}, {single,true}]},{{1,"bits"},skip_member}]}, + '~wxBitmap',%'AddHandler','CleanUpHandlers', + 'ConvertToImage', + 'CopyFromIcon','Create',%'FindHandler', + 'GetDepth','GetHeight',%'GetHandlers', + 'GetPalette', + 'GetMask','GetWidth','GetSubBitmap', + %%'InitStandardHandlers','InsertHandler','RemoveHandler', + 'LoadFile','Ok','SaveFile','SetDepth', + 'SetHeight','SetMask','SetPalette', + 'SetWidth']}. + +{class, wxIcon, wxBitmap,[], + [%%{'wxIcon',[{"bits",[in,{base,binary}]}]}, + {'wxIcon',[{"bits",skip_member}]}, %% bits is char** in gtk and char[] in mac!!! + 'CopyFromBitmap','~wxIcon']}. + +{class, wxIconBundle, root, [], + ['wxIconBundle','~wxIconBundle','AddIcon','GetIcon']}. + +{class, wxCursor, wxBitmap,[], + [{'wxCursor',[{"bits",[in,{base,binary},{single,true}]}, + {"maskBits",nowhere},{"fg",nowhere},{"bg",nowhere}]}, + '~wxCursor','Ok']}. + +{class, wxMask, object, [], ['wxMask','~wxMask','Create']}. + +{class, wxImage, object, [{doc,"All (default) image handlers are initialized."}], + [{'wxImage',[{"xpmData",skip_member}, + {"data",[in,{base,binary}]}, + {"alpha",[in,{base,binary}]}, + {{4,pre_hook}, + "if(!static_data) {" + "data = (unsigned char *) malloc(Ecmd.bin[0]->size);" + "memcpy(data,Ecmd.bin[0]->base,Ecmd.bin[0]->size);}"}, + {{5,pre_hook}, + "if(!static_data) {" + " data = (unsigned char *) malloc(Ecmd.bin[0]->size);" + " alpha = (unsigned char *) malloc(Ecmd.bin[1]->size);" + " memcpy(data,Ecmd.bin[0]->base,Ecmd.bin[0]->size);" + " memcpy(alpha,Ecmd.bin[1]->base,Ecmd.bin[1]->size);}"} + ]}, + '~wxImage',%'AddHandler', + 'Blur','BlurHorizontal','BlurVertical', + %'CleanUpHandlers',%'ComputeHistogram', + 'ConvertAlphaToMask','ConvertToGreyscale', + 'ConvertToMono','Copy', + {'Create',[{"xpmData",skip_member}, + {"data",[in,{base,binary}]}, + {"alpha",[in,{base,binary}]}, + {{4,pre_hook}, + "if(!static_data) {" + "data = (unsigned char *) malloc(Ecmd.bin[0]->size);" + "memcpy(data,Ecmd.bin[0]->base,Ecmd.bin[0]->size);}"}, + {{5,pre_hook}, + "if(!static_data) {" + " data = (unsigned char *) malloc(Ecmd.bin[0]->size);" + " alpha = (unsigned char *) malloc(Ecmd.bin[1]->size);" + " memcpy(data,Ecmd.bin[0]->base,Ecmd.bin[0]->size);" + " memcpy(alpha,Ecmd.bin[1]->base,Ecmd.bin[1]->size);}"} + ]}, + 'Destroy','FindFirstUnusedColour', % 'FindHandler', + 'GetImageExtWildcard', + {'GetAlpha',[{{0,return},{base,{binary,"(This->GetWidth()*This->GetHeight())"}}}]}, + 'GetBlue', + {'GetData', [{return,{base,{binary,"(This->GetWidth()*This->GetHeight()*3)"}}}]}, + 'GetGreen', 'GetImageCount', %'GetHandlers', + 'GetHeight','GetMaskBlue','GetMaskGreen', + 'GetMaskRed','GetOrFindMaskColour','GetPalette', + 'GetRed','GetSubImage', 'GetWidth',%%':HSVValue', 'HSVtoRGB', + 'HasAlpha','HasMask','GetOption','GetOptionInt','HasOption', + 'InitAlpha','InitStandardHandlers',%'InsertHandler', + 'IsTransparent', 'LoadFile','Ok',%%RGBValue 'RGBtoHSV', + 'RemoveHandler','Mirror','Replace','Rescale','Resize', + 'Rotate', 'RotateHue', + 'Rotate90','SaveFile','Scale','Size', + {'SetAlpha', [{{2,"alpha"},[in,{base,binary}, {def, none}]}, + {{2,pre_hook}, + "if(!static_data) {" + "alpha = (unsigned char *) malloc(Ecmd.bin[0]->size);" + "memcpy(alpha,Ecmd.bin[0]->base,Ecmd.bin[0]->size);}"} + ]}, + {'SetData', [{"data",[in,{base,binary}]}, + {pre_hook, + "if(!static_data) {" + "data = (unsigned char *) malloc(Ecmd.bin[0]->size);" + "memcpy(data,Ecmd.bin[0]->base,Ecmd.bin[0]->size);}"} + ]}, + 'SetMask','SetMaskColour','SetMaskFromImage','SetOption', + 'SetPalette', + 'SetRGB']}. + +{class, wxBrush, object, [], + ['wxBrush','~wxBrush','GetColour','GetStipple','GetStyle', + 'IsHatch','IsOk','SetColour','SetStipple','SetStyle']}. + +{class, wxPen, object, [], + ['wxPen','~wxPen','GetCap','GetColour', + %%'GetDashes', %'GetStipple', + 'GetJoin', 'GetStyle','GetWidth','IsOk','SetCap','SetColour', + %%'SetDashes', %'SetStipple', + 'SetJoin', 'SetStyle','SetWidth']}. + +{enum, wxRegionContain, "wx"}. + +{class, wxRegion, object, + [{skip, [{wxRegion,3}]}], % Hmm compiler can't handle that + [{'wxRegion',[{"region", [skip_member]}]}, + '~wxRegion','Clear','Contains','ConvertToBitmap', + {'GetBox',0},'Intersect','IsEmpty','Subtract','Offset', + 'Union','Xor']}. + +{class, wxAcceleratorTable, object, + [{skip, [{wxAcceleratorTable,1}]}], + ['wxAcceleratorTable','~wxAcceleratorTable','Ok']}. + +{class, wxAcceleratorEntry, root, [], + ['wxAcceleratorEntry','GetCommand','GetFlags','GetKeyCode','Set']}. + +{class, wxCaret, root, + [{skip, [{wxCaret,0}]}], + ['wxCaret','~wxCaret','Create','GetBlinkTime','GetPosition','GetSize','GetWindow','Hide','IsOk', + 'IsVisible','Move','SetBlinkTime','SetSize','Show']}. + +{enum, wxFlexSizerGrowMode, "wxFLEX_GROWMODE_"}. + +{class, wxSizer, object, [], + [{'Add',[{"item", skip_member}]}, + 'AddSpacer','AddStretchSpacer','CalcMin','Clear','Detach','Fit','FitInside', + 'GetChildren',%'GetContainingWindow', + 'GetItem','GetSize','GetPosition','GetMinSize', + 'Hide','Insert','InsertSpacer','InsertStretchSpacer','IsShown','Layout','Prepend', + 'PrependSpacer','PrependStretchSpacer','RecalcSizes','Remove', 'Replace', + 'SetDimension','SetMinSize','SetItemMinSize','SetSizeHints', + 'SetVirtualSizeHints','Show']}. + +{class, wxSizerFlags, root, [], + ['wxSizerFlags','Align','Border','Center','Centre',%'DoubleBorder','DoubleHorzBorder', + 'Expand',%'GetDefaultBorder', + 'Left','Proportion','Right'%,'TripleBorder' + ]}. + +{class, wxSizerItem, object, [], + ['wxSizerItem','~wxSizerItem','CalcMin','DeleteWindows','DetachSizer','GetBorder', + 'GetFlag','GetMinSize','GetPosition','GetProportion','GetRatio','GetRect','GetSize', + 'GetSizer','GetSpacer','GetUserData','GetWindow','IsSizer','IsShown','IsSpacer', + 'IsWindow','SetBorder','SetDimension','SetFlag','SetInitSize','SetMinSize', + 'SetProportion','SetRatio','SetSizer','SetSpacer','SetWindow','Show']}. + +{class,wxBoxSizer,wxSizer,[],['wxBoxSizer','GetOrientation']}. +{class,wxStaticBoxSizer,wxBoxSizer,[],['wxStaticBoxSizer','GetStaticBox']}. + +{class,wxGridSizer,wxSizer,[], + ['wxGridSizer','GetCols','GetHGap','GetRows','GetVGap','SetCols','SetHGap', + 'SetRows','SetVGap']}. + +{class,wxFlexGridSizer,wxGridSizer,[], + ['wxFlexGridSizer','AddGrowableCol','AddGrowableRow','GetFlexibleDirection', + 'GetNonFlexibleGrowMode','RemoveGrowableCol','RemoveGrowableRow', + 'SetFlexibleDirection','SetNonFlexibleGrowMode']}. + +{class,wxGridBagSizer,wxFlexGridSizer,[], + ['wxGridBagSizer','Add','CalcMin','CheckForIntersection','FindItem', + 'FindItemAtPoint','FindItemAtPosition','FindItemWithData','GetCellSize', + 'GetEmptyCellSize','GetItemPosition','GetItemSpan', + 'SetEmptyCellSize','SetItemPosition','SetItemSpan']}. + +{class,wxGBSizerItem,wxSizerItem,[],[]}. +%% [{skip, [{'GetEndPos',3},{'GetPos',3},{'GetSpan',3}]}], +%% ['wxGBSizerItem','GetEndPos','GetPos','GetSpan','Intersects','SetPos','SetSpan']}. + +{class,wxStdDialogButtonSizer,wxBoxSizer,[], + ['wxStdDialogButtonSizer','~wxStdDialogButtonSizer','AddButton','Realize', + 'SetAffirmativeButton','SetCancelButton','SetNegativeButton']}. + +{enum, wxFontFamily, "wxFONTFAMILY_"}. +{enum, wxFontStyle, "wxFONTSTYLE_"}. +{enum, wxFontEncoding,"wxFONTENCODING_"}. + +{class, wxFont, object, [], + [{'wxFont',[{"info", [skip_member]},{"family",{base,{enum,"wxFontFamily"}}}, + {"style",{base,{enum,"wxFontStyle"}}}]}, + '~wxFont','IsFixedWidth','GetDefaultEncoding','GetFaceName', + {'GetFamily',[{return, {base,{enum,"wxFontFamily"}}}]}, + 'GetNativeFontInfoDesc','GetNativeFontInfoUserDesc','GetPointSize', + {'GetStyle',[{return, {base,{enum,"wxFontStyle"}}}]}, + 'GetUnderlined','GetWeight',%% {'New',[{"nativeFontDesc", [skip_member]}]}, + 'Ok','SetDefaultEncoding','SetFaceName', + {'SetFamily',[{"family", {base,{enum,"wxFontFamily"}}}]}, + %%'SetNativeFontInfo','SetNativeFontInfoUserDesc', + 'SetPointSize', + {'SetStyle', [{"style", {base,{enum,"wxFontStyle"}}}]}, + 'SetUnderlined','SetWeight']}. + +{class, wxToolTip, object, [], + ['Enable','SetDelay','wxToolTip','SetTip','GetTip','GetWindow']}. +{class, wxButton, wxControl, [], + ['wxButton','~wxButton','Create',%'GetLabel', + 'GetDefaultSize', 'SetDefault','SetLabel']}. +{class, wxBitmapButton, wxButton, [], + ['wxBitmapButton','~wxBitmapButton','Create','GetBitmapDisabled', + 'GetBitmapFocus','GetBitmapLabel','GetBitmapSelected', + 'SetBitmapDisabled','SetBitmapFocus','SetBitmapLabel','SetBitmapSelected']}. +{class, wxToggleButton, wxControl, [], + ['wxToggleButton','~wxToggleButton','Create','GetValue','SetValue']}. + +%%{enum, {"wxDateTime", "WeekDay"}, "wxDateTime::WeekDay"}. +{class, wxDateTime, root, [ignore], []}. %% Only for ifdefs and enums + +{class, wxCalendarCtrl, wxControl, [], + ['wxCalendarCtrl','Create','~wxCalendarCtrl','SetDate','GetDate', + 'EnableYearChange','EnableMonthChange','EnableHolidayDisplay', + 'SetHeaderColours','GetHeaderColourFg','GetHeaderColourBg', + 'SetHighlightColours','GetHighlightColourFg','GetHighlightColourBg', + 'SetHolidayColours','GetHolidayColourFg','GetHolidayColourBg', + 'GetAttr','SetAttr','SetHoliday','ResetAttr', + {'HitTest', [{"date", [out]}, {"wd", [out]}]} + ]}. + +{class, wxCalendarDateAttr, root, [], + ['wxCalendarDateAttr', + 'SetTextColour','SetBackgroundColour','SetBorderColour', + 'SetFont','SetBorder','SetHoliday', + 'HasTextColour','HasBackgroundColour','HasBorderColour', + 'HasFont','HasBorder','IsHoliday','GetTextColour', + 'GetBackgroundColour','GetBorderColour','GetFont','GetBorder']}. + +{enum, wxCheckBoxState, "wxCHK_"}. + +{class, wxCheckBox, wxControl, [], + ['wxCheckBox','~wxCheckBox','Create','GetValue','Get3StateValue', + 'Is3rdStateAllowedForUser','Is3State','IsChecked','SetValue', + 'Set3StateValue']}. +{class, wxCheckListBox, wxListBox, [{skip,[{wxCheckListBox,8}]}], + [{'wxCheckListBox',[{"pos",{def, "wxDefaultPosition"}}, + {"size",{def, "wxDefaultSize"}}, + {"choices",{def, ""}}]}, + '~wxCheckListBox','Check','IsChecked']}. +{class, wxChoice, wxControlWithItems, [{skip,[{wxChoice,8}, {'Create',9}]}], + [{'wxChoice', [{"pos",{def, "wxDefaultPosition"}}, + {"size",{def, "wxDefaultSize"}}, + {"choices",{def, ""}}]}, + '~wxChoice','Create','Delete','GetColumns', + %%'GetCurrentSelection', + 'SetColumns']}. +{class, wxComboBox, wxControlWithItems, [{skip,[{wxComboBox,9},{'Create',10}]}], + [{'wxComboBox', + [{"pos",{def, "wxDefaultPosition"}}, + {"size",{def, "wxDefaultSize"}}, + {"value", {def, "wxEmptyString"}}, + {"choices",{def, ""}}]}, + '~wxComboBox','Create','CanCopy','CanCut','CanPaste', + 'CanRedo','CanUndo','Copy','Cut','GetInsertionPoint','GetLastPosition', + 'GetValue','Paste','Redo','Replace','Remove','SetInsertionPoint', + 'SetInsertionPointEnd','SetSelection','SetValue','Undo']}. +{class, wxGauge, wxControl, [], + ['wxGauge','~wxGauge','Create','GetBezelFace','GetRange','GetShadowWidth', + 'GetValue','IsVertical','SetBezelFace','SetRange','SetShadowWidth','SetValue', + 'Pulse']}. +{class, wxGenericDirCtrl, wxControl, [], + ['wxGenericDirCtrl','~wxGenericDirCtrl','Create','Init','CollapseTree', + 'ExpandPath','GetDefaultPath','GetPath','GetFilePath', 'GetFilter', + 'GetFilterIndex',%'GetFilterListCtrl', + 'GetRootId','GetTreeCtrl', + 'ReCreateTree','SetDefaultPath','SetFilter','SetFilterIndex','SetPath']}. +%% {class, wxHtmlListBox, wxControl, [], []}. +{class, wxStaticBox, wxControl, [], ['wxStaticBox','~wxStaticBox','Create']}. +{class, wxStaticLine, wxControl, [], ['wxStaticLine','~wxStaticLine','Create', + 'IsVertical', 'GetDefaultSize']}. + +{enum, wxListColumnFormat, "wxLIST_"}. + +{class, wxListBox, wxControlWithItems, + [{skip,[{wxListBox,8}, {'Create',9}, {'Set',4}]}], + [{'wxListBox',[{"pos",{def, "wxDefaultPosition"}}, + {"size",{def, "wxDefaultSize"}}, + {"choices",{def, ""}}]}, + '~wxListBox','Create','Deselect',{'GetSelections',[{"aSelections", [out]}]}, + {'InsertItems',2},'IsSelected',{'Set',[{"clientData",[skip]}]}, + 'HitTest', + 'SetFirstItem']}. + +{class, wxListCtrl, wxControl, [], + ['wxListCtrl','~wxListCtrl','Arrange','AssignImageList','ClearAll','Create', + 'DeleteAllItems','DeleteColumn','DeleteItem', + {'EditLabel',[{"textControlClass",nowhere}]}, + 'EnsureVisible', + {'FindItem',3},'GetColumn','GetColumnCount','GetColumnWidth','GetCountPerPage', + %%'GetEditControl', + 'GetImageList','GetItem','GetItemBackgroundColour', + 'GetItemCount',{'GetItemData', [{return, {base,int}}]}, + 'GetItemFont','GetItemPosition','GetItemRect', + 'GetItemSpacing','GetItemState','GetItemText','GetItemTextColour', + 'GetNextItem','GetSelectedItemCount','GetTextColour','GetTopItem', + 'GetViewRect',{'HitTest',[{"pSubItem",nowhere}]},'InsertColumn','InsertItem', + %%'OnGetItemAttr', 'OnGetItemImage','OnGetItemText', + 'RefreshItem','RefreshItems','ScrollList', + 'SetBackgroundColour','SetColumn','SetColumnWidth','SetImageList','SetItem', + 'SetItemBackgroundColour','SetItemCount','SetItemData','SetItemFont', + 'SetItemImage','SetItemColumnImage','SetItemPosition','SetItemState', + 'SetItemText','SetItemTextColour','SetSingleStyle','SetTextColour', + 'SetWindowStyleFlag',{'SortItems', [{where, taylormade}]} + ]}. +{class, wxListView, wxControl, [], + ['ClearColumnImage','Focus','GetFirstSelected','GetFocusedItem', + 'GetNextSelected','IsSelected','Select','SetColumnImage']}. + +{class, wxListItem, object, [], + ['wxListItem','~wxListItem','Clear','GetAlign','GetBackgroundColour','GetColumn', %'GetData', + 'GetFont','GetId','GetImage','GetMask','GetState', + 'GetText','GetTextColour','GetWidth','SetAlign','SetBackgroundColour', + 'SetColumn',%'SetData', + 'SetFont','SetId','SetImage','SetMask','SetState', + 'SetStateMask','SetText','SetTextColour','SetWidth']}. + +{class, wxImageList, object, [{skip, [{'Create',1}]}], %% No create/0 on windows + ['wxImageList','~wxImageList','Add','Create','Draw','GetBitmap','GetIcon','GetImageCount', + 'GetSize','Remove','RemoveAll','Replace']}. + +{enum, wxTextAttrAlignment, "wxTEXT_ALIGNMENT_"}. + +{class, wxTextAttr, root, [], + ['wxTextAttr','GetAlignment','GetBackgroundColour','GetFont','GetLeftIndent', + 'GetLeftSubIndent','GetRightIndent','GetTabs','GetTextColour', + 'HasBackgroundColour','HasFont','HasTextColour','GetFlags','IsDefault', + 'SetAlignment','SetBackgroundColour','SetFlags','SetFont','SetLeftIndent', + 'SetRightIndent','SetTabs','SetTextColour']}. + +{class, wxTextCtrl, wxControl, [], + ['wxTextCtrl','~wxTextCtrl','AppendText','CanCopy','CanCut','CanPaste', + 'CanRedo','CanUndo','Clear','Copy','Create','Cut','DiscardEdits', + 'EmulateKeyPress','GetDefaultStyle','GetInsertionPoint','GetLastPosition', + 'GetLineLength','GetLineText','GetNumberOfLines','GetRange','GetSelection', + 'GetStringSelection','GetStyle','GetValue',%'HitTest', %no Mac + 'IsEditable', + 'IsModified','IsMultiLine','IsSingleLine','LoadFile','MarkDirty', + %%'OnDropFiles', + 'Paste','PositionToXY','Redo','Remove','Replace', + 'SaveFile','SetDefaultStyle','SetEditable','SetInsertionPoint', + 'SetInsertionPointEnd','SetMaxLength','SetSelection','SetStyle', + 'SetValue','ShowPosition','Undo','WriteText','XYToPosition']}. + +{class,wxNotebook, wxControl, [], + ['wxNotebook','~wxNotebook','AddPage','AdvanceSelection', + 'AssignImageList','Create','DeleteAllPages', + %% Remove 'page' only defined for motif + {'DeletePage', [{"page", skip_member}]}, {'RemovePage', [{"page", skip_member}]}, + 'GetCurrentPage','GetImageList','GetPage','GetPageCount', + 'GetPageImage','GetPageText','GetRowCount','GetSelection', + 'GetThemeBackgroundColour', + 'HitTest', + 'InsertPage', + %%'OnSelChange', callback + 'SetImageList','SetPadding','SetPageSize', + 'SetPageImage','SetPageText','SetSelection','ChangeSelection']}. + +{class,wxChoicebook, wxControl, [], + ['wxChoicebook','~wxChoicebook','AddPage','AdvanceSelection', + 'AssignImageList','Create','DeleteAllPages', + %% Remove 'page' only defined for motif + {'DeletePage', [{"page", skip_member}]}, {'RemovePage', [{"page", skip_member}]}, + 'GetCurrentPage','GetImageList','GetPage','GetPageCount', + 'GetPageImage','GetPageText', + %% NOTEBOOK ONLY? 'GetRowCount', 'GetThemeBackgroundColour','SetPadding' + 'GetSelection', + 'HitTest', + 'InsertPage', + %%'OnSelChange', callback + 'SetImageList','SetPageSize', + 'SetPageImage','SetPageText','SetSelection','ChangeSelection']}. + +{class,wxToolbook, wxControl, [], + ['wxToolbook','~wxToolbook','AddPage','AdvanceSelection', + 'AssignImageList','Create','DeleteAllPages', + %% Remove 'page' only defined for motif + {'DeletePage', [{"page", skip_member}]}, {'RemovePage', [{"page", skip_member}]}, + 'GetCurrentPage','GetImageList','GetPage','GetPageCount', + 'GetPageImage','GetPageText', + %% NOTEBOOK ONLY? 'GetRowCount', 'GetThemeBackgroundColour','SetPadding' + 'GetSelection', + 'HitTest', + 'InsertPage', + %%'OnSelChange', callback + 'SetImageList','SetPageSize', + 'SetPageImage','SetPageText','SetSelection','ChangeSelection']}. + +{class,wxListbook, wxControl, [], + ['wxListbook','~wxListbook','AddPage','AdvanceSelection', + 'AssignImageList','Create','DeleteAllPages', + %% Remove 'page' only defined for motif + {'DeletePage', [{"page", skip_member}]}, {'RemovePage', [{"page", skip_member}]}, + 'GetCurrentPage','GetImageList','GetPage','GetPageCount', + 'GetPageImage','GetPageText', + %% NOTEBOOK ONLY? 'GetRowCount', 'GetThemeBackgroundColour','SetPadding' + 'GetSelection', + 'HitTest', + 'InsertPage', + %%'OnSelChange', callback + 'SetImageList','SetPageSize', + 'SetPageImage','SetPageText','SetSelection','ChangeSelection']}. + +{class,wxTreebook, wxControl, [], + ['wxTreebook','~wxTreebook','AddPage','AdvanceSelection', + 'AssignImageList','Create','DeleteAllPages', + %% Remove 'page' only defined for motif + {'DeletePage', [{"page", skip_member}]}, {'RemovePage', [{"page", skip_member}]}, + 'GetCurrentPage','GetImageList','GetPage','GetPageCount', + 'GetPageImage','GetPageText', + %% NOTEBOOK ONLY? 'GetRowCount', 'GetThemeBackgroundColour','SetPadding' + 'GetSelection', + 'ExpandNode', 'IsNodeExpanded', + 'HitTest', + 'InsertPage','InsertSubPage', + %%'OnSelChange', callback + 'SetImageList','SetPageSize', + 'SetPageImage','SetPageText','SetSelection','ChangeSelection']}. + + +{enum, wxTreeItemIcon, "wxTreeItemIcon_"}. + +{class, wxTreeCtrl, wxControl, [], + ['wxTreeCtrl','~wxTreeCtrl','AddRoot','AppendItem', + %% Not on Windows 'AssignButtonsImageList','GetButtonsImageList','SetButtonsImageList' + 'AssignImageList','AssignStateImageList','Collapse','CollapseAndReset', + 'Create','Delete','DeleteAllItems','DeleteChildren',{'EditLabel',1}, + %'EndEditLabel', + 'EnsureVisible','Expand','GetBoundingRect', + 'GetChildrenCount','GetCount','GetEditControl', + %'GetFirstChild', + 'GetFirstVisibleItem',{'GetImageList',0},'GetIndent', + 'GetItemBackgroundColour','GetItemData','GetItemFont','GetItemImage', + 'GetItemText','GetItemTextColour','GetLastChild', % 'GetNextChild', + 'GetNextSibling','GetNextVisible','GetItemParent',%'GetParent', + 'GetPrevSibling','GetPrevVisible','GetRootItem', + 'GetSelection',{'GetSelections', [{return, nowhere},{"val",out}]}, + 'GetStateImageList',{'HitTest', 1}, + {'InsertItem',[{"insertAfter", skip_member}]}, + 'IsBold','IsExpanded','IsSelected','IsVisible','ItemHasChildren', + %%'OnCompareItems', + 'PrependItem','ScrollTo','SelectItem', + 'SetIndent',{'SetImageList',1},'SetItemBackgroundColour', + 'SetItemBold','SetItemData','SetItemDropHighlight','SetItemFont', + 'SetItemHasChildren','SetItemImage','SetItemText', + 'SetItemTextColour','SetStateImageList','SetWindowStyle',{'SortChildren',1}, + 'Toggle','ToggleItemSelection','Unselect','UnselectAll','UnselectItem']}. + +{class, wxScrollBar, wxControl, [], + ['wxScrollBar','~wxScrollBar','Create','GetRange','GetPageSize', + 'GetThumbPosition','GetThumbSize','SetThumbPosition','SetScrollbar']}. +{class, wxSpinButton, wxControl, [], + ['wxSpinButton','~wxSpinButton','Create','GetMax','GetMin','GetValue','SetRange','SetValue']}. +{class, wxSpinCtrl, wxControl, [], + ['wxSpinCtrl','Create','SetValue','GetValue','SetRange','SetSelection','GetMin','GetMax']}. + +{class, wxStaticText, wxControl, [], + ['wxStaticText','Create','GetLabel','SetLabel','Wrap']}. +{class, wxStaticBitmap, wxControl, [], + ['wxStaticBitmap','Create','GetBitmap','SetBitmap' + %%wxStaticIcon::GetIcon wxStaticIcon::SetIcon + ]}. +{class, wxRadioBox, wxControl, [], + [{'wxRadioBox',9},'~wxRadioBox',{'Create',9},'Enable', + 'GetSelection','GetString', 'SetSelection','Show', + 'GetColumnCount','GetItemHelpText','GetItemToolTip','GetItemFromPoint', + 'GetRowCount', 'IsItemEnabled','IsItemShown','SetItemHelpText','SetItemToolTip' + ]}. +{class, wxRadioButton, wxControl, [], + ['wxRadioButton','~wxRadioButton','Create','GetValue','SetValue']}. + +{class, wxSlider, wxControl, [], + ['wxSlider','~wxSlider', %'ClearSel','ClearTicks', + 'Create','GetLineSize','GetMax','GetMin', + 'GetPageSize',%'GetSelEnd','GetSelStart', + 'GetThumbLength',%'GetTickFreq', + 'GetValue', + 'SetLineSize','SetPageSize','SetRange',%'SetSelection', + 'SetThumbLength',%'SetTick', 'SetTickFreq', + 'SetValue']}. + +{class, wxDialog, wxTopLevelWindow, [], + ['wxDialog','~wxDialog',%'Centre', + 'Create','CreateButtonSizer', + 'CreateStdDialogButtonSizer',%'DoOK', + 'EndModal','GetAffirmativeId', + 'GetReturnCode', %'GetTitle','GetToolBar','Iconize','IsIconized', + 'IsModal', + %%'OnApply','OnCancel','OnOK', 'OnSysColourChanged', + 'SetAffirmativeId', %'SetIcon','SetIcons','SetTitle', + %% 'SetModal', Deprecated + 'SetReturnCode','Show','ShowModal']}. + +{class, wxColourDialog, wxDialog, [], + ['wxColourDialog','~wxColourDialog','Create','GetColourData']}. + +{class, wxColourData, object, [], + ['wxColourData','~wxColourData','GetChooseFull','GetColour','GetCustomColour', + 'SetChooseFull','SetColour','SetCustomColour']}. + +{class, wxPalette, object, [], + [{'wxPalette',[{"n", {c_only,{size,0}}},{"red",[in,{base,binary}]}, + {"green", [in,{base,binary}]},{"blue", [in,{base,binary}]}]}, + '~wxPalette', + {'Create', [{"n", {c_only,{size,0}}},{"red",[in,{base,binary}]}, + {"green", [in,{base,binary}]},{"blue", [in,{base,binary}]}]}, + 'GetColoursCount','GetPixel', + 'GetRGB', + 'IsOk']}. + +{class, wxGenericDirDialog, wxDialog, + [{alias, [{wxGenericDirDialog,wxDirDialog}]}, {skip, [{wxDirDialog,0}]}], + ['wxDirDialog','~wxDirDialog','GetPath','GetMessage','SetMessage', + 'SetPath']}. + +{class, wxFileDialog, wxDialog, [{skip, [{wxFileDialog,0}]}], + ['wxFileDialog','~wxFileDialog','GetDirectory','GetFilename', + {'GetFilenames',[{"files", out}]}, + 'GetFilterIndex','GetMessage','GetPath','GetPaths','GetWildcard', + 'SetDirectory','SetFilename','SetFilterIndex','SetMessage','SetPath', + 'SetWildcard']}. + +%% {class, wxGenericFileDialog, wxDialog, [], +%% ['wxFileDialog','~wxFileDialog','GetDirectory','GetFilename','GetFilenames', +%% 'GetFilterIndex','GetMessage','GetPath','GetPaths','GetStyle','GetWildcard', +%% 'SetDirectory','SetFilename','SetFilterIndex','SetMessage','SetPath','SetStyle', +%% 'SetWildcard']}. + +{class, wxPickerBase, wxControl, [], + ['SetInternalMargin','GetInternalMargin','SetTextCtrlProportion', + 'SetPickerCtrlProportion','GetTextCtrlProportion','GetPickerCtrlProportion', + 'HasTextCtrl','GetTextCtrl','IsTextCtrlGrowable','SetPickerCtrlGrowable', + 'SetTextCtrlGrowable','IsPickerCtrlGrowable']}. + +{class, wxFilePickerCtrl, wxPickerBase, [], + ['wxFilePickerCtrl','Create','GetPath','SetPath']}. + +{class, wxDirPickerCtrl, wxPickerBase, [], + ['wxDirPickerCtrl','Create','GetPath','SetPath']}. + +{class, wxColourPickerCtrl, wxPickerBase, [], + ['wxColourPickerCtrl','Create','GetColour','SetColour']}. + +{class, wxDatePickerCtrl, wxPickerBase, [], + ['wxDatePickerCtrl', %'Create', + 'GetRange', 'GetValue', %'SetFormat', Not always available + 'SetRange', 'SetValue']}. + +{class, wxFontPickerCtrl, wxPickerBase, [], + ['wxFontPickerCtrl','Create','GetSelectedFont','SetSelectedFont', + 'GetMaxPointSize','SetMaxPointSize']}. + +{class, wxGenericFindReplaceDialog, wxDialog, + [{alias, [{wxGenericFindReplaceDialog,wxFindReplaceDialog}]}], + ['wxFindReplaceDialog','~wxFindReplaceDialog','Create','GetData']}. + +{class, wxFindReplaceData, object, [], + ['wxFindReplaceData','~wxFindReplaceData','GetFindString','GetReplaceString', + 'GetFlags','SetFlags','SetFindString','SetReplaceString']}. + +{class, wxMultiChoiceDialog, wxDialog, [{skip, [{wxMultiChoiceDialog, 7}]}], + ['wxMultiChoiceDialog','GetSelections','SetSelections']}. +{class, wxSingleChoiceDialog, wxDialog, [{skip, [{wxSingleChoiceDialog, 8}]}], + [{'wxSingleChoiceDialog', [{"clientData", [skip,in]}]}, + 'GetSelection', %% 'GetSelectionClientData', obsolete + 'GetStringSelection','SetSelection']}. + +{class, wxTextEntryDialog, wxDialog, [], + ['wxTextEntryDialog','~wxTextEntryDialog','GetValue','SetValue']}. + +{class, wxPasswordEntryDialog, wxTextEntryDialog, [], ['wxPasswordEntryDialog']}. + +{class, wxFontData, object, [], + ['wxFontData','~wxFontData', + 'EnableEffects','GetAllowSymbols','GetColour','GetChosenFont', + 'GetEnableEffects','GetInitialFont','GetShowHelp','SetAllowSymbols', + 'SetChosenFont','SetColour','SetInitialFont','SetRange','SetShowHelp']}. + +{class, wxFontDialog, wxDialog, + [{skip, [{'wxFontDialog',1}, {'Create',2}]}], %% Not available on Mac!! + ['wxFontDialog','Create','GetFontData']}. + +{class, wxProgressDialog, wxDialog, [], + ['wxProgressDialog','~wxProgressDialog','Resume',{'Update', [{"skip", nowhere}]}]}. +{class, wxMessageDialog, wxDialog, [], + ['wxMessageDialog', '~wxMessageDialog']}. + +{enum, wxPrintBin, "wxPRINTBIN_"}. +{enum, wxDuplexMode, "wxDUPLEX_"}. +{enum, wxPrintMode, "wxPRINT_MODE_"}. +%%{enum, wxPaperSize,"wxPAPER_"}. + +{class, wxPageSetupDialog, object, [], + ['wxPageSetupDialog','~wxPageSetupDialog','GetPageSetupData', 'ShowModal']}. + +{class, wxPageSetupDialogData, object, [], + ['wxPageSetupDialogData','~wxPageSetupDialogData','EnableHelp','EnableMargins', + 'EnableOrientation','EnablePaper','EnablePrinter','GetDefaultMinMargins', + 'GetEnableMargins','GetEnableOrientation','GetEnablePaper','GetEnablePrinter', + 'GetEnableHelp','GetDefaultInfo','GetMarginTopLeft','GetMarginBottomRight', + 'GetMinMarginTopLeft','GetMinMarginBottomRight','GetPaperId','GetPaperSize', + 'GetPrintData','IsOk','SetDefaultInfo','SetDefaultMinMargins','SetMarginTopLeft', + 'SetMarginBottomRight','SetMinMarginTopLeft','SetMinMarginBottomRight', + 'SetPaperId','SetPaperSize','SetPrintData']}. +{class, wxPrintDialog, wxDialog, [], + ['wxPrintDialog','~wxPrintDialog','GetPrintDialogData','GetPrintDC']}. +{class,wxPrintDialogData, object, [], + ['wxPrintDialogData','~wxPrintDialogData','EnableHelp','EnablePageNumbers', + 'EnablePrintToFile','EnableSelection','GetAllPages','GetCollate','GetFromPage', + 'GetMaxPage','GetMinPage','GetNoCopies','GetPrintData','GetPrintToFile', + 'GetSelection','GetToPage','IsOk','SetCollate','SetFromPage','SetMaxPage', + 'SetMinPage','SetNoCopies','SetPrintData','SetPrintToFile','SetSelection', + %%'SetSetupDialog', not found + 'SetToPage']}. + +{class, wxPrintData, object, [], + ['wxPrintData','~wxPrintData','GetCollate','GetBin','GetColour', + 'GetDuplex','GetNoCopies','GetOrientation','GetPaperId','GetPrinterName', + 'GetQuality','IsOk','SetBin','SetCollate','SetColour','SetDuplex','SetNoCopies', + 'SetOrientation','SetPaperId','SetPrinterName','SetQuality']}. + +{class, wxPrintPreview, object, [], + ['wxPrintPreview','~wxPrintPreview','GetCanvas','GetCurrentPage', + 'GetFrame','GetMaxPage','GetMinPage','GetPrintout','GetPrintoutForPrinting', + 'IsOk','PaintPage','Print','RenderPage','SetCanvas','SetCurrentPage', + 'SetFrame','SetPrintout','SetZoom']}. + +{class, wxPreviewFrame, wxFrame, [], + ['wxPreviewFrame','~wxPreviewFrame','CreateControlBar','CreateCanvas', + 'Initialize','OnCloseWindow']}. + +{class, wxPreviewControlBar, wxPanel, [], +['wxPreviewControlBar','~wxPreviewControlBar','CreateButtons','GetPrintPreview', + 'GetZoomControl','SetZoomControl']}. + +{class, wxPreviewCanvas, wxScrolledWindow, [], []}. + +{class, wxPrinter, object, [], + ['wxPrinter','CreateAbortWindow','GetAbort','GetLastError', + 'GetPrintDialogData','Print','PrintDialog','ReportError','Setup']}. + +{class, wxXmlResource, object, [], + ['wxXmlResource', '~wxXmlResource', + %%'AddHandler', removed wxXmlResourceHandler is not implemented yet + 'AttachUnknownControl', + 'ClearHandlers', 'CompareVersion', + 'Get', 'GetFlags', 'GetVersion', + {'GetXRCID', [{"str_id", [{single, array}]}]}, + 'InitAllHandlers', 'Load', + 'LoadBitmap', 'LoadDialog', 'LoadFrame', 'LoadIcon', 'LoadMenu', 'LoadMenuBar', 'LoadPanel', + 'LoadToolBar', 'Set', 'SetFlags', 'Unload', + {xrcctrl,[{where, taylormade}]} + %,{'GetDomain', [{return, [{single, array}]}]}, 'SetDomain' + ]}. + +{class, wxHtmlEasyPrinting, object, [], + ['wxHtmlEasyPrinting','~wxHtmlEasyPrinting', + %'GetParentWindow', Not found + 'GetPrintData','GetPageSetupData','PreviewFile', + 'PreviewText','PrintFile','PrintText','PageSetup', + {'SetFonts',[{"sizes", [{single, array}, {def, "(int *) NULL"}]}]}, + 'SetHeader','SetFooter'%,'SetParentWindow' + ]}. + +%%{class, wxVListBox, wxControl, [], []}. + +{class, wxGLCanvas, wxWindow, + [{skip, [{'SetCurrent', 2}]}], %% NA MAC + [{'wxGLCanvas', [{"attribList", [in, {single,array}]}]}, + 'GetContext', + {'SetCurrent', [{post_hook,"if(This->GetContext()) setActiveGL(Ecmd.caller,This)"}]}, + %%{'SetColour', [{"colour", [in, {single,array}]}]}, + 'SwapBuffers']}. + +%% {class, wxGLContext, wxWindow, [], %% NA MAC or rather looks different on mac FIXME +%% ['wxGLContext','SetCurrent']}. + +{class, wxAuiManager, wxEvtHandler, [{ifdef, wxUSE_AUI}], + ['wxAuiManager','~wxAuiManager','AddPane','DetachPane','GetAllPanes', + 'GetArtProvider','GetDockSizeConstraint','GetFlags','GetManagedWindow', + 'GetManager','GetPane','HideHint','InsertPane','LoadPaneInfo', + 'LoadPerspective',%'ProcessDockResult', Protected can be derived + 'SavePaneInfo','SavePerspective', + 'SetArtProvider','SetDockSizeConstraint','SetFlags','SetManagedWindow', + 'ShowHint','UnInit','Update']}. + +{class, wxAuiPaneInfo, root, [{ifdef, wxUSE_AUI}], + [ + wxAuiPaneInfo,'~wxAuiPaneInfo', + 'BestSize','Bottom','BottomDockable','Caption','CaptionVisible', + 'Centre','CentrePane','CloseButton','DefaultPane','DestroyOnClose', + 'Direction','Dock',%'DockFixed', + 'Dockable','Fixed','Float', + 'Floatable','FloatingPosition','FloatingSize','Gripper','GripperTop', + 'HasBorder','HasCaption','HasCloseButton','HasFlag', + 'HasGripper','HasGripperTop','HasMaximizeButton','HasMinimizeButton', + 'HasPinButton','Hide','IsBottomDockable','IsDocked','IsFixed', + 'IsFloatable','IsFloating','IsLeftDockable','IsMovable','IsOk', + 'IsResizable','IsRightDockable','IsShown','IsToolbar','IsTopDockable', + 'Layer','Left','LeftDockable','MaxSize','MaximizeButton', + 'MinSize','MinimizeButton','Movable','Name', + 'PaneBorder','PinButton','Position','Resizable','Right', + 'RightDockable','Row','SafeSet','SetFlag','Show','ToolbarPane', + 'Top','TopDockable','Window']}. + +{class, wxAuiNotebook, wxControl, [{ifdef, wxUSE_AUI}], + ['wxAuiNotebook','AddPage',%'AdvanceSelection', + 'Create','DeletePage', + 'GetArtProvider',%%'GetHeightForPageHeight','GetTabCtrlHeight', not found + 'GetPage','GetPageBitmap', + 'GetPageCount','GetPageIndex','GetPageText','GetSelection', + 'InsertPage','RemovePage','SetArtProvider', + 'SetFont',%'SetNormalFont','SetSelectedFont','SetMeasuringFont',not found + 'SetPageBitmap','SetPageText','SetSelection','SetTabCtrlHeight', + 'SetUniformBitmapSize'%,'ShowWindowMenu' + ]}. + +{class,wxAuiTabArt, root, [{ifdef, wxUSE_AUI}], + [% Pure virtual funcs + %'Clone','DrawBackground','DrawButton','DrawTab','GetBestTabCtrlSize', + %'GetIndentSize','GetTabSize','SetFlags','SetMeasuringFont', + %'SetNormalFont','SetSelectedFont','SetSizingInfo'%,'ShowWindowList' + ]}. + +{class,wxAuiDockArt, root, [{ifdef, wxUSE_AUI}], + [%% 'wxAuiDockArt','~wxAuiDockArt' %, + %%'DrawBackground','DrawBorder','DrawCaption', %% Pure virtual funcs + %%'DrawGripper','DrawPaneButton','DrawSash', + %%'GetColor','GetColour','GetFont','GetMetric','SetColor','SetColour','SetFont','SetMetric' + ]}. + +{class, wxMDIParentFrame, wxFrame, [], + [ + 'wxMDIParentFrame', '~wxMDIParentFrame', 'ActivateNext', 'ActivatePrevious', + 'ArrangeIcons', 'Cascade', 'Create', + %%'GetClientSize', 'GetToolBar', 'SetToolBar', defined in parent + 'GetActiveChild', 'GetClientWindow', + %% 'GetWindowMenu', 'SetWindowMenu', windows only + %%'OnCreateClient', + 'Tile']}. + +{class, wxMDIChildFrame, wxFrame, [], + ['wxMDIChildFrame','~wxMDIChildFrame','Activate','Create','Maximize','Restore']}. + +{class, wxMDIClientWindow, wxWindow, [], + ['wxMDIClientWindow','~wxMDIClientWindow','CreateClient']}. + +{class, wxLayoutAlgorithm, object, [], + ['wxLayoutAlgorithm', '~wxLayoutAlgorithm', + 'LayoutFrame', 'LayoutMDIFrame', 'LayoutWindow']}. + +%%%% EVENT's + +{class, wxEvent, object, [], + [%%'wxEvent','m','propagationLevel','Clone','GetEventObject','GetEventType', + 'GetId','GetSkipped', + {'GetTimestamp', [{return, [{mod,[unsigned]}]}]}, + 'IsCommandEvent','ResumePropagation', + %% 'SetEventObject','SetEventType','SetId','SetTimestamp', + 'ShouldPropagate','Skip','StopPropagation' + ]}. + +{class, wxCommandEvent, wxEvent, + [{acc, [{m_cmdString, "GetString()"}, + {m_commandInt, "GetInt()"}, {m_extraLong,"GetExtraLong()"}]}, + {event, + [wxEVT_COMMAND_BUTTON_CLICKED,wxEVT_COMMAND_CHECKBOX_CLICKED, + wxEVT_COMMAND_CHOICE_SELECTED,wxEVT_COMMAND_LISTBOX_SELECTED, + wxEVT_COMMAND_LISTBOX_DOUBLECLICKED,wxEVT_COMMAND_TEXT_UPDATED, + wxEVT_COMMAND_TEXT_ENTER,wxEVT_COMMAND_MENU_SELECTED, + wxEVT_COMMAND_SLIDER_UPDATED,wxEVT_COMMAND_RADIOBOX_SELECTED, + wxEVT_COMMAND_RADIOBUTTON_SELECTED,wxEVT_COMMAND_SCROLLBAR_UPDATED, + wxEVT_COMMAND_VLBOX_SELECTED,wxEVT_COMMAND_COMBOBOX_SELECTED, + %% wxEVT_COMMAND_TOOL_CLICKED, This the exactly the same as command_menu_selected + %% I can't differ them + wxEVT_COMMAND_TOOL_RCLICKED, + wxEVT_COMMAND_TOOL_ENTER, wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, + wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, + wxEVT_COMMAND_LEFT_CLICK,wxEVT_COMMAND_LEFT_DCLICK,wxEVT_COMMAND_RIGHT_CLICK, + wxEVT_COMMAND_SET_FOCUS, wxEVT_COMMAND_KILL_FOCUS, + wxEVT_COMMAND_ENTER + ]}], + [{'GetClientObject',[{erl_func, "getClientData"}]}, + 'GetExtraLong','GetInt','GetSelection','GetString','IsChecked', + 'IsSelection',%'SetClientData','SetClientObject','SetExtraLong', + 'SetInt','SetString' + ]}. + +{class, wxScrollEvent, wxCommandEvent, + [{acc, [{m_commandInt, "GetPosition()"}, {m_extraLong, "GetOrientation()"}]}, + {mixed_event, wxSpinEvent}, + {event, + [wxEVT_SCROLL_TOP,wxEVT_SCROLL_BOTTOM,wxEVT_SCROLL_LINEUP, + wxEVT_SCROLL_LINEDOWN,wxEVT_SCROLL_PAGEUP, + wxEVT_SCROLL_PAGEDOWN,wxEVT_SCROLL_THUMBTRACK, + wxEVT_SCROLL_THUMBRELEASE,wxEVT_SCROLL_CHANGED]}], + ['GetOrientation','GetPosition']}. +{class, wxScrollWinEvent,wxEvent, + [{event, + [wxEVT_SCROLLWIN_TOP,wxEVT_SCROLLWIN_BOTTOM,wxEVT_SCROLLWIN_LINEUP, + wxEVT_SCROLLWIN_LINEDOWN,wxEVT_SCROLLWIN_PAGEUP, + wxEVT_SCROLLWIN_PAGEDOWN,wxEVT_SCROLLWIN_THUMBTRACK, + wxEVT_SCROLLWIN_THUMBRELEASE]}], + ['GetOrientation','GetPosition']}. + +{class, wxMouseEvent, wxEvent, + [{event, + [wxEVT_LEFT_DOWN,wxEVT_LEFT_UP,wxEVT_MIDDLE_DOWN,wxEVT_MIDDLE_UP, + wxEVT_RIGHT_DOWN,wxEVT_RIGHT_UP,wxEVT_MOTION,wxEVT_ENTER_WINDOW, + wxEVT_LEAVE_WINDOW,wxEVT_LEFT_DCLICK,wxEVT_MIDDLE_DCLICK, + wxEVT_RIGHT_DCLICK,wxEVT_MOUSEWHEEL, + wxEVT_NC_LEFT_DOWN,wxEVT_NC_LEFT_UP, + wxEVT_NC_MIDDLE_DOWN,wxEVT_NC_MIDDLE_UP,wxEVT_NC_RIGHT_DOWN, + wxEVT_NC_RIGHT_UP,wxEVT_NC_MOTION,wxEVT_NC_ENTER_WINDOW, + wxEVT_NC_LEAVE_WINDOW,wxEVT_NC_LEFT_DCLICK,wxEVT_NC_MIDDLE_DCLICK, + wxEVT_NC_RIGHT_DCLICK]}], + ['AltDown','Button','ButtonDClick','ButtonDown','ButtonUp','CmdDown','ControlDown', + 'Dragging', 'Entering', 'GetButton', 'GetPosition', 'GetLogicalPosition', + 'GetLinesPerAction', 'GetWheelRotation', 'GetWheelDelta', 'GetX', 'GetY', + 'IsButton', 'IsPageScroll', 'Leaving', + 'LeftDClick', 'LeftDown', 'LeftIsDown', 'LeftUp', + 'MetaDown', + 'MiddleDClick', 'MiddleDown', 'MiddleIsDown', 'MiddleUp', + 'Moving', + 'RightDClick', 'RightDown', 'RightIsDown', 'RightUp', + 'ShiftDown' + ]}. + +{class, wxSetCursorEvent, wxEvent, [{event,[wxEVT_SET_CURSOR]}], + ['GetCursor','GetX','GetY','HasCursor','SetCursor']}. + +{class, wxKeyEvent, wxEvent, + [{event,[wxEVT_CHAR,wxEVT_CHAR_HOOK, + wxEVT_KEY_DOWN,wxEVT_KEY_UP %,wxEVT_HOTKEY + ]}], + ['AltDown','CmdDown','ControlDown','GetKeyCode', + 'GetModifiers','GetPosition','GetRawKeyCode','GetRawKeyFlags', + 'GetUnicodeKey','GetX','GetY','HasModifiers','MetaDown', + 'ShiftDown' + ]}. + +{class, wxSizeEvent, wxEvent, [{event,[wxEVT_SIZE]}], + ['GetSize']}. +{class, wxMoveEvent, wxEvent, [{event,[wxEVT_MOVE]}], + ['GetPosition']}. +{class, wxPaintEvent, wxEvent, [{event,[wxEVT_PAINT,wxEVT_PAINT_ICON]}],[]}. +{class, wxNcPaintEvent, wxEvent, [{event,[wxEVT_NC_PAINT]}],[]}. +{class, wxEraseEvent, wxEvent, + [{acc, [{m_dc, "GetDC()"}]}, + {event, [wxEVT_ERASE_BACKGROUND]}], + ['GetDC']}. +{class, wxFocusEvent, wxEvent, + [{event,[wxEVT_SET_FOCUS,wxEVT_KILL_FOCUS]}], + ['GetWindow']}. +{class,wxChildFocusEvent,wxCommandEvent, + [{event,[wxEVT_CHILD_FOCUS]}], + ['GetWindow']}. + +%% {class, wxActivateEvent, wxEvent, [{event, +%% [wxEVT_ACTIVATE,wxEVT_ACTIVATE_APP,wxEVT_HIBERNATE]}],[]}. + +%%{class, wxInitDialogEvent, wxEvent, [{event, []}],[]}. + +{class, wxMenuEvent, wxEvent, + [{event, [wxEVT_MENU_OPEN,wxEVT_MENU_CLOSE,wxEVT_MENU_HIGHLIGHT]}], + ['GetMenu','GetMenuId','IsPopup']}. +{class, wxCloseEvent, wxEvent, + [{event, [wxEVT_CLOSE_WINDOW,wxEVT_END_SESSION,wxEVT_QUERY_END_SESSION]}], + ['CanVeto','GetLoggingOff','SetCanVeto','SetLoggingOff','Veto']}. +{class, wxShowEvent, wxEvent, [{event,[wxEVT_SHOW]}],['SetShow','GetShow']}. +{class, wxIconizeEvent, wxEvent, [{event,[wxEVT_ICONIZE]}],['Iconized']}. +{class, wxMaximizeEvent, wxEvent, [{event,[wxEVT_MAXIMIZE]}],[]}. +{class, wxJoystickEvent, wxEvent, + [{event,[wxEVT_JOY_BUTTON_DOWN,wxEVT_JOY_BUTTON_UP, + wxEVT_JOY_MOVE,wxEVT_JOY_ZMOVE]}], + ['ButtonDown','ButtonIsDown','ButtonUp','GetButtonChange','GetButtonState', + 'GetJoystick','GetPosition','GetZPosition','IsButton','IsMove','IsZMove']}. + +%% {class, wxDropFilesEvent, wxEvent, [{event,[wxEVT_DROP_FILES]}],[]}. %FIXME + +{enum, wxUpdateUIMode, "wxUPDATE_UI_"}. + +{class, wxUpdateUIEvent, wxCommandEvent, + [{event,[wxEVT_UPDATE_UI]}], + ['CanUpdate','Check','Enable','Show','GetChecked','GetEnabled','GetShown', + 'GetSetChecked','GetSetEnabled','GetSetShown','GetSetText','GetText', + 'GetMode','GetUpdateInterval','ResetUpdateTime','SetMode','SetText', + 'SetUpdateInterval']}. +{class, wxSysColourChangedEvent, wxEvent, + [{event,[wxEVT_SYS_COLOUR_CHANGED]}],[]}. +{class, wxMouseCaptureChangedEvent, wxEvent, + [{event,[wxEVT_MOUSE_CAPTURE_CHANGED]}],['GetCapturedWindow']}. +{class, wxDisplayChangedEvent, wxEvent, [{event,[wxEVT_DISPLAY_CHANGED]}],[]}. +{class, wxPaletteChangedEvent, wxEvent, + [{event,[wxEVT_PALETTE_CHANGED]}],['SetChangedWindow','GetChangedWindow']}. +{class, wxQueryNewPaletteEvent, wxEvent, + [{event,[wxEVT_QUERY_NEW_PALETTE]}],['SetPaletteRealized','GetPaletteRealized']}. +{class, wxNavigationKeyEvent, wxEvent, [{event,[wxEVT_NAVIGATION_KEY]}], + ['GetDirection','SetDirection','IsWindowChange','SetWindowChange', + 'IsFromTab','SetFromTab','GetCurrentFocus','SetCurrentFocus']}. +{class, wxWindowCreateEvent, wxCommandEvent, [{event,[wxEVT_CREATE]}],[]}. +{class, wxWindowDestroyEvent, wxCommandEvent, [{event,[wxEVT_DESTROY]}],[]}. +{enum, {"wxHelpEvent","Origin"}, "wxHelpEvent::Origin_"}. +{class, wxHelpEvent, wxEvent, [{event,[wxEVT_HELP,wxEVT_DETAILED_HELP]}], + [%%{'GetOrigin', [{return, [{type,"wxHelpEvent::Origin"}]}]}, + 'GetOrigin', + 'GetPosition', + %%{'SetOrigin', [{"origin", [{type,"wxHelpEvent::Origin"}]}]}, + 'SetOrigin', + 'SetPosition']}. + +{class, wxContextMenuEvent, wxCommandEvent, [{event,[wxEVT_CONTEXT_MENU]}], + ['GetPosition','SetPosition']}. +{enum, wxIdleMode, "wxIDLE_"}. +{class, wxIdleEvent, wxEvent, [{event,[wxEVT_IDLE]}], + ['CanSend','GetMode','RequestMore','MoreRequested','SetMode']}. +{class, wxGridEvent, wxNotifyEvent, + [{acc, [{m_row, "GetRow()"}, {m_col, "GetCol()"}, {m_x, "GetPosition().x"},{m_y, "GetPosition().y"}, + {m_selecting, "Selecting()"},{m_control,"ControlDown()"}, + {m_meta, "MetaDown()"}, {m_shift, "ShiftDown()"},{m_alt,"AltDown()"}]}, + {event,[wxEVT_GRID_CELL_LEFT_CLICK, wxEVT_GRID_CELL_RIGHT_CLICK, wxEVT_GRID_CELL_LEFT_DCLICK, + wxEVT_GRID_CELL_RIGHT_DCLICK, wxEVT_GRID_LABEL_LEFT_CLICK, wxEVT_GRID_LABEL_RIGHT_CLICK, + wxEVT_GRID_LABEL_LEFT_DCLICK, wxEVT_GRID_LABEL_RIGHT_DCLICK, wxEVT_GRID_ROW_SIZE, + wxEVT_GRID_COL_SIZE, wxEVT_GRID_RANGE_SELECT, wxEVT_GRID_CELL_CHANGE, wxEVT_GRID_SELECT_CELL, + wxEVT_GRID_EDITOR_SHOWN, wxEVT_GRID_EDITOR_HIDDEN, wxEVT_GRID_EDITOR_CREATED, + wxEVT_GRID_CELL_BEGIN_DRAG]}], + ['AltDown','ControlDown','GetCol','GetPosition','GetRow','MetaDown','Selecting','ShiftDown']}. + +{class, wxNotifyEvent, wxCommandEvent, [], ['Allow','IsAllowed','Veto']}. + +{enum, wxSashDragStatus, ""}. +{enum, wxSashEdgePosition, ""}. +{class, wxSashEvent, wxCommandEvent, + [{acc, [{m_edge, "GetEdge()"}, {m_dragStatus,"GetDragStatus()"}, {m_dragRect,"GetDragRect()"}]}, + {event,[wxEVT_SASH_DRAGGED + %% , wxEVT_SASH_DRAGGED_RANGE Non exitent use connect with id, lastId + ]}], + ['GetEdge','GetDragRect','GetDragStatus']}. + +{class, wxListEvent, wxNotifyEvent, + [{acc, [{m_itemIndex, "GetIndex()"}, {m_code, "GetKeyCode()"}, + {m_pointDrag, "GetPoint()"}, {m_item, skip}]}, + {event, [wxEVT_COMMAND_LIST_BEGIN_DRAG,wxEVT_COMMAND_LIST_BEGIN_RDRAG, + wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT,wxEVT_COMMAND_LIST_END_LABEL_EDIT, + wxEVT_COMMAND_LIST_DELETE_ITEM,wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, + wxEVT_COMMAND_LIST_KEY_DOWN, + wxEVT_COMMAND_LIST_INSERT_ITEM, + wxEVT_COMMAND_LIST_COL_CLICK,wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, + wxEVT_COMMAND_LIST_COL_BEGIN_DRAG,wxEVT_COMMAND_LIST_COL_DRAGGING, + wxEVT_COMMAND_LIST_COL_END_DRAG, + + wxEVT_COMMAND_LIST_ITEM_SELECTED,wxEVT_COMMAND_LIST_ITEM_DESELECTED, + wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK,wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK, + wxEVT_COMMAND_LIST_ITEM_ACTIVATED,wxEVT_COMMAND_LIST_ITEM_FOCUSED, + + wxEVT_COMMAND_LIST_CACHE_HINT]}], + [ + 'GetCacheFrom','GetCacheTo','GetKeyCode','GetIndex','GetColumn', + 'GetPoint','GetLabel','GetText','GetImage','GetData','GetMask','GetItem', + 'IsEditCancelled' + ]}. + +{class, wxDateEvent, wxCommandEvent, + [{acc, [{m_date, "GetDate()"}]}, {event,[wxEVT_DATE_CHANGED]}], + [ + 'GetDate' + ]}. + +{class, wxCalendarEvent, wxDateEvent, + [{event,[wxEVT_CALENDAR_SEL_CHANGED, wxEVT_CALENDAR_DAY_CHANGED, + wxEVT_CALENDAR_MONTH_CHANGED, wxEVT_CALENDAR_YEAR_CHANGED, + wxEVT_CALENDAR_DOUBLECLICKED, wxEVT_CALENDAR_WEEKDAY_CLICKED]}], + [ + 'GetWeekDay' + ]}. + +{class, wxFileDirPickerEvent, wxCommandEvent, + [{event, [wxEVT_COMMAND_FILEPICKER_CHANGED, wxEVT_COMMAND_DIRPICKER_CHANGED]}, + {acc, [{m_path, "GetPath()"}]}], + ['GetPath']}. + +{class, wxColourPickerEvent, wxCommandEvent, + [{event, [wxEVT_COMMAND_COLOURPICKER_CHANGED]}, + {acc, [{m_colour, "GetColour()"}]}], + ['GetColour']}. + +{class, wxFontPickerEvent, wxCommandEvent, + [{event, [wxEVT_COMMAND_FONTPICKER_CHANGED]}, + {acc, [{m_font, "GetFont()"}]}], + ['GetFont']}. + +{class, wxStyledTextEvent, wxCommandEvent, + [{event, [wxEVT_STC_CHANGE, wxEVT_STC_STYLENEEDED, wxEVT_STC_CHARADDED, + wxEVT_STC_SAVEPOINTREACHED, wxEVT_STC_SAVEPOINTLEFT, wxEVT_STC_ROMODIFYATTEMPT, + wxEVT_STC_KEY,wxEVT_STC_DOUBLECLICK,wxEVT_STC_UPDATEUI,wxEVT_STC_MODIFIED, + wxEVT_STC_MACRORECORD,wxEVT_STC_MARGINCLICK,wxEVT_STC_NEEDSHOWN,wxEVT_STC_PAINTED, + wxEVT_STC_USERLISTSELECTION,wxEVT_STC_URIDROPPED,wxEVT_STC_DWELLSTART, + wxEVT_STC_DWELLEND,wxEVT_STC_START_DRAG,wxEVT_STC_DRAG_OVER,wxEVT_STC_DO_DROP, + wxEVT_STC_ZOOM,wxEVT_STC_HOTSPOT_CLICK,wxEVT_STC_HOTSPOT_DCLICK, + wxEVT_STC_CALLTIP_CLICK,wxEVT_STC_AUTOCOMP_SELECTION]}, + {acc, [{m_position,"GetPosition()"},{m_key,"GetKey()"}, {m_modifiers,"GetModifiers()"}, + {m_modificationType,"GetModificationType()"},{m_text,"GetText()"}, + {m_length,"GetLength()"},{m_linesAdded,"GetLinesAdded()"},{m_line,"GetLine()"}, + {m_foldLevelNow,"GetFoldLevelNow()"}, {m_foldLevelPrev,"GetFoldLevelPrev()"}, + {m_margin,"GetMargin()"}, {m_message,"GetMessage()"}, {m_wParam,"GetWParam()"}, + {m_lParam,"GetLParam()"}, {m_listType,"GetListType()"},{m_x,"GetX()"}, + {m_y,"GetY()"}, {m_dragText,"GetDragText()"}, {m_dragAllowMove,"GetDragAllowMove()"}, + {m_dragResult,"GetDragResult()"}]}], + ['GetPosition','GetKey','GetModifiers','GetModificationType','GetText','GetLength', + 'GetLinesAdded','GetLine','GetFoldLevelNow','GetFoldLevelPrev','GetMargin', + 'GetMessage','GetWParam','GetLParam','GetListType','GetX','GetY', + 'GetDragText','GetDragAllowMove','GetDragResult','GetShift','GetControl','GetAlt']}. + +%%{class, , wxEvent, [{event,[]}],[]}. + + +%% Testing generation on static classless funcs +{class, utils, static, [], + ['wxGetKeyState', 'wxGetMousePosition', 'wxGetMouseState', + 'wxSetDetectableAutoRepeat', + 'wxBell', + 'wxFindMenuItemId', 'wxGenericFindWindowAtPoint', 'wxFindWindowAtPoint', + 'wxBeginBusyCursor', 'wxEndBusyCursor', 'wxIsBusy', + 'wxShutdown', {'wxShell', 1}, 'wxLaunchDefaultBrowser', + {'wxGetEmailAddress',0}, {'wxGetUserId',0}, {'wxGetHomeDir',0}, + 'wxNewId', 'wxRegisterId', 'wxGetCurrentId', + 'wxGetOsDescription', 'wxIsPlatformLittleEndian', 'wxIsPlatform64Bit' + ]}. + +{class, wxPrintout, object, [{alias, [{wxePrintout, wxePrintout}]}], + [{'wxPrintout', [{where, taylormade}]},'~wxPrintout', + 'GetDC', %% 'GetPageInfo',Callback + 'GetPageSizeMM','GetPageSizePixels','GetPaperRectPixels', + 'GetPPIPrinter','GetPPIScreen','GetTitle', %% 'HasPage', Callback + 'IsPreview', + 'FitThisSizeToPaper','FitThisSizeToPage','FitThisSizeToPageMargins', + 'MapScreenSizeToPaper','MapScreenSizeToPage','MapScreenSizeToPageMargins','MapScreenSizeToDevice', + 'GetLogicalPaperRect','GetLogicalPageRect','GetLogicalPageMarginsRect','SetLogicalOrigin', + 'OffsetLogicalOrigin']}. + +%%%%%%%%%%%%%%%% +%% Test requires stc +{class, wxStyledTextCtrl, wxControl, [], + ['wxStyledTextCtrl','~wxStyledTextCtrl','Create', 'AddText', 'AddStyledText', 'InsertText', + 'ClearAll', 'ClearDocumentStyle', 'GetLength', 'GetCharAt', 'GetCurrentPos', 'GetAnchor', + 'GetStyleAt', 'Redo', 'SetUndoCollection', 'SelectAll', 'SetSavePoint', 'GetStyledText', + 'CanRedo', 'MarkerLineFromHandle', 'MarkerDeleteHandle', 'GetUndoCollection', + 'GetViewWhiteSpace', 'SetViewWhiteSpace', + 'PositionFromPoint', 'PositionFromPointClose', 'GotoLine', 'GotoPos', 'SetAnchor', + {'GetCurLine', [{"linePos", [out]}]}, 'GetEndStyled', 'ConvertEOLs', 'GetEOLMode', 'SetEOLMode', + 'StartStyling', 'SetStyling', 'GetBufferedDraw', 'SetBufferedDraw', 'SetTabWidth', 'GetTabWidth', + 'SetCodePage', 'MarkerDefine', 'MarkerSetForeground', 'MarkerSetBackground', 'MarkerAdd', 'MarkerDelete', + 'MarkerDeleteAll', 'MarkerGet', 'MarkerNext', 'MarkerPrevious', 'MarkerDefineBitmap', 'MarkerAddSet', + 'MarkerSetAlpha', 'SetMarginType', 'GetMarginType', 'SetMarginWidth', 'GetMarginWidth', 'SetMarginMask', + 'GetMarginMask', 'SetMarginSensitive', 'GetMarginSensitive', 'StyleClearAll', 'StyleSetForeground', + 'StyleSetBackground', 'StyleSetBold', 'StyleSetItalic', 'StyleSetSize', 'StyleSetFaceName', + 'StyleSetEOLFilled', 'StyleResetDefault', 'StyleSetUnderline', 'StyleSetCase', 'StyleSetHotSpot', + 'SetSelForeground', 'SetSelBackground', 'GetSelAlpha', 'SetSelAlpha', 'SetCaretForeground', + 'CmdKeyAssign', 'CmdKeyClear', 'CmdKeyClearAll', 'SetStyleBytes', 'StyleSetVisible', 'GetCaretPeriod', + 'SetCaretPeriod', 'SetWordChars', 'BeginUndoAction', 'EndUndoAction', 'IndicatorSetStyle', + 'IndicatorGetStyle', 'IndicatorSetForeground', 'IndicatorGetForeground', 'SetWhitespaceForeground', + 'SetWhitespaceBackground', 'GetStyleBits', 'SetLineState', 'GetLineState', 'GetMaxLineState', + 'GetCaretLineVisible', 'SetCaretLineVisible', 'GetCaretLineBackground', 'SetCaretLineBackground', + 'AutoCompShow', 'AutoCompCancel', 'AutoCompActive', 'AutoCompPosStart', 'AutoCompComplete', + 'AutoCompStops', 'AutoCompSetSeparator', 'AutoCompGetSeparator', 'AutoCompSelect', + 'AutoCompSetCancelAtStart', 'AutoCompGetCancelAtStart', 'AutoCompSetFillUps', 'AutoCompSetChooseSingle', + 'AutoCompGetChooseSingle', 'AutoCompSetIgnoreCase', 'AutoCompGetIgnoreCase', 'UserListShow', + 'AutoCompSetAutoHide', 'AutoCompGetAutoHide', 'AutoCompSetDropRestOfWord', 'AutoCompGetDropRestOfWord', + 'RegisterImage', 'ClearRegisteredImages', 'AutoCompGetTypeSeparator', 'AutoCompSetTypeSeparator', + 'AutoCompSetMaxWidth', 'AutoCompGetMaxWidth', 'AutoCompSetMaxHeight', 'AutoCompGetMaxHeight', + 'SetIndent', 'GetIndent', 'SetUseTabs', 'GetUseTabs', 'SetLineIndentation', 'GetLineIndentation', + 'GetLineIndentPosition', 'GetColumn', 'SetUseHorizontalScrollBar', 'GetUseHorizontalScrollBar', + 'SetIndentationGuides', 'GetIndentationGuides', 'SetHighlightGuide', 'GetHighlightGuide', + 'GetLineEndPosition', 'GetCodePage', 'GetCaretForeground', 'GetReadOnly', 'SetCurrentPos', + 'SetSelectionStart', 'GetSelectionStart', 'SetSelectionEnd', 'GetSelectionEnd', 'SetPrintMagnification', + 'GetPrintMagnification', 'SetPrintColourMode', 'GetPrintColourMode', 'FindText', 'FormatRange', + 'GetFirstVisibleLine', 'GetLine', 'GetLineCount', 'SetMarginLeft', 'GetMarginLeft', 'SetMarginRight', + 'GetMarginRight', 'GetModify', 'SetSelection', 'GetSelectedText', 'GetTextRange', 'HideSelection', + 'LineFromPosition', 'PositionFromLine', 'LineScroll', 'EnsureCaretVisible', 'ReplaceSelection', + 'SetReadOnly', 'CanPaste', 'CanUndo', 'EmptyUndoBuffer', 'Undo', 'Cut', 'Copy', 'Paste', 'Clear', + 'SetText', 'GetText', 'GetTextLength', 'GetOvertype', 'SetCaretWidth', 'GetCaretWidth', + 'SetTargetStart', 'GetTargetStart', 'SetTargetEnd', 'GetTargetEnd', 'ReplaceTarget', 'SearchInTarget', + 'SetSearchFlags', 'GetSearchFlags', 'CallTipShow', 'CallTipCancel', 'CallTipActive', 'CallTipPosAtStart', + 'CallTipSetHighlight', 'CallTipSetBackground', 'CallTipSetForeground', 'CallTipSetForegroundHighlight', + 'CallTipUseStyle', 'VisibleFromDocLine', 'DocLineFromVisible', 'WrapCount', 'SetFoldLevel', 'GetFoldLevel', + 'GetLastChild', 'GetFoldParent', 'ShowLines', 'HideLines', 'GetLineVisible', 'SetFoldExpanded', + 'GetFoldExpanded', 'ToggleFold', 'EnsureVisible', 'SetFoldFlags', 'EnsureVisibleEnforcePolicy', + 'SetTabIndents', 'GetTabIndents', 'SetBackSpaceUnIndents', 'GetBackSpaceUnIndents', 'SetMouseDwellTime', + 'GetMouseDwellTime', 'WordStartPosition', 'WordEndPosition', 'SetWrapMode', 'GetWrapMode', + 'SetWrapVisualFlags', 'GetWrapVisualFlags', 'SetWrapVisualFlagsLocation', 'GetWrapVisualFlagsLocation', + 'SetWrapStartIndent', 'GetWrapStartIndent', 'SetLayoutCache', 'GetLayoutCache', 'SetScrollWidth', + 'GetScrollWidth', 'TextWidth', 'GetEndAtLastLine', 'TextHeight', 'SetUseVerticalScrollBar', + 'GetUseVerticalScrollBar', 'AppendText', 'GetTwoPhaseDraw', 'SetTwoPhaseDraw', 'TargetFromSelection', + 'LinesJoin', 'LinesSplit', 'SetFoldMarginColour', 'SetFoldMarginHiColour', 'LineDown', 'LineDownExtend', + 'LineUp', 'LineUpExtend', 'CharLeft', 'CharLeftExtend', 'CharRight', 'CharRightExtend', 'WordLeft', + 'WordLeftExtend', 'WordRight', 'WordRightExtend', 'Home', 'HomeExtend', 'LineEnd', 'LineEndExtend', + 'DocumentStart', 'DocumentStartExtend', 'DocumentEnd', 'DocumentEndExtend', 'PageUp', 'PageUpExtend', + 'PageDown', 'PageDownExtend', 'EditToggleOvertype', 'Cancel', 'DeleteBack', 'Tab', 'BackTab', 'NewLine', + 'FormFeed', 'VCHome', 'VCHomeExtend', 'ZoomIn', 'ZoomOut', 'DelWordLeft', 'DelWordRight', 'LineCut', + 'LineDelete', 'LineTranspose', 'LineDuplicate', 'LowerCase', 'UpperCase', 'LineScrollDown', 'LineScrollUp', + 'DeleteBackNotLine', 'HomeDisplay', 'HomeDisplayExtend', 'LineEndDisplay', 'LineEndDisplayExtend', + 'HomeWrapExtend', 'LineEndWrap', 'LineEndWrapExtend', 'VCHomeWrap', 'VCHomeWrapExtend', 'LineCopy', + 'MoveCaretInsideView', 'LineLength', 'BraceHighlight', 'BraceBadLight', 'BraceMatch', 'GetViewEOL', + 'SetViewEOL', %'GetDocPointer', 'SetDocPointer', Hmm void pointers + 'SetModEventMask', 'GetEdgeColumn', 'SetEdgeColumn', + 'GetEdgeMode', 'GetEdgeColour', 'SetEdgeColour', 'SearchAnchor', 'SearchNext', + 'SearchPrev', 'LinesOnScreen', + 'UsePopUp', 'SelectionIsRectangle', 'SetZoom', 'GetZoom', + %%'CreateDocument', 'AddRefDocument', 'ReleaseDocument', Hmm void pointers + 'GetModEventMask', 'SetSTCFocus', 'GetSTCFocus', 'SetStatus', 'GetStatus', + 'SetMouseDownCaptures', 'GetMouseDownCaptures', 'SetSTCCursor', 'GetSTCCursor', + 'SetControlCharSymbol', 'GetControlCharSymbol', 'WordPartLeft', + 'WordPartLeftExtend', 'WordPartRight', 'WordPartRightExtend', + 'SetVisiblePolicy', 'DelLineLeft', 'DelLineRight', + 'GetXOffset', 'ChooseCaretX', 'SetXCaretPolicy', + 'SetYCaretPolicy', 'GetPrintWrapMode', + 'SetHotspotActiveForeground', 'SetHotspotActiveBackground', + 'SetHotspotActiveUnderline', 'SetHotspotSingleLine', + 'ParaDownExtend', 'ParaUp', 'ParaUpExtend', + 'PositionBefore', 'PositionAfter', 'CopyRange', 'CopyText', + 'SetSelectionMode', 'GetSelectionMode', 'LineDownRectExtend', + 'LineUpRectExtend', 'CharLeftRectExtend', 'CharRightRectExtend', + 'HomeRectExtend', 'VCHomeRectExtend', + 'LineEndRectExtend', 'PageUpRectExtend', 'PageDownRectExtend', + 'StutteredPageUp', 'StutteredPageUpExtend', 'StutteredPageDown', 'StutteredPageDownExtend', + 'WordLeftEnd', 'WordLeftEndExtend', 'WordRightEnd', + 'WordRightEndExtend', 'SetWhitespaceChars', 'SetCharsDefault', 'AutoCompGetCurrent', 'Allocate', + 'FindColumn', 'GetCaretSticky', 'SetCaretSticky', 'ToggleCaretSticky', 'SetPasteConvertEndings', + 'GetPasteConvertEndings', 'SelectionDuplicate', 'SetCaretLineBackAlpha', 'GetCaretLineBackAlpha', + 'StartRecord', 'StopRecord', 'SetLexer', 'GetLexer', 'Colourise', 'SetProperty', 'SetKeyWords', + 'SetLexerLanguage', 'GetProperty', 'GetStyleBitsNeeded', 'GetCurrentLine', 'StyleSetSpec', + 'StyleSetFont', 'StyleSetFontAttr', 'StyleSetCharacterSet', 'StyleSetFontEncoding', + 'CmdKeyExecute', + 'SetMargins', {'GetSelection', [{"startPos", [out]}, {"endPos",[out]}]}, + 'PointFromPosition', 'ScrollToLine', 'ScrollToColumn', 'SendMsg', + 'SetVScrollBar', 'SetHScrollBar', 'GetLastKeydownProcessed', 'SetLastKeydownProcessed', + 'SaveFile', 'LoadFile', 'DoDragOver', 'DoDropText', 'GetUseAntiAliasing', + {'AddTextRaw', [{"text", [in, {base, binary}]}]}, + {'InsertTextRaw', [{"text", [in, {base, binary}]}]}, + {'GetCurLineRaw', [{return,{base,{binary,"strlen(Result)"}}}, {"linePos", [out]}]}, + {'GetLineRaw',[{return,{base,{binary,"strlen(Result)"}}}]}, + {'GetSelectedTextRaw', [{return,{base,{binary,"strlen(Result)"}}}]}, + {'GetTextRangeRaw', [{return,{base,{binary,"strlen(Result)"}}}]}, + {'SetTextRaw', [{"text", [in, {base, binary}]}]}, + {'GetTextRaw', [{return,{base,{binary,"strlen(Result)"}}}]}, + {'AppendTextRaw', [{"text", [in, {base, binary}]}]}]}. + +{class, wxArtProvider, object, [], + [{'GetBitmap', [{"client", {def,"wxART_OTHER"}}]}, + {'GetIcon', [{"client", {def,"wxART_OTHER"}}]}]}. + +{class, wxTreeEvent, wxNotifyEvent, + [{acc, [{m_item, "GetItem()"}, {m_itemOld, "GetOldItem()"}, + {m_pointDrag, "GetPoint()"}]}, + {event, [wxEVT_COMMAND_TREE_BEGIN_DRAG, wxEVT_COMMAND_TREE_BEGIN_RDRAG, + wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, wxEVT_COMMAND_TREE_END_LABEL_EDIT, + wxEVT_COMMAND_TREE_DELETE_ITEM, wxEVT_COMMAND_TREE_GET_INFO, + wxEVT_COMMAND_TREE_SET_INFO, wxEVT_COMMAND_TREE_ITEM_EXPANDED, + wxEVT_COMMAND_TREE_ITEM_EXPANDING, wxEVT_COMMAND_TREE_ITEM_COLLAPSED, + wxEVT_COMMAND_TREE_ITEM_COLLAPSING, wxEVT_COMMAND_TREE_SEL_CHANGED, + wxEVT_COMMAND_TREE_SEL_CHANGING, wxEVT_COMMAND_TREE_KEY_DOWN, + wxEVT_COMMAND_TREE_ITEM_ACTIVATED, wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, + wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK, wxEVT_COMMAND_TREE_END_DRAG, + wxEVT_COMMAND_TREE_STATE_IMAGE_CLICK, wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP, + wxEVT_COMMAND_TREE_ITEM_MENU]} + ], + ['GetKeyCode','GetItem','GetKeyEvent','GetLabel','GetOldItem','GetPoint', + 'IsEditCancelled','SetToolTip']}. + +{class, wxNotebookEvent, wxNotifyEvent, + [{event, [wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, + wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING]}], + ['GetOldSelection','GetSelection','SetOldSelection','SetSelection']}. + + +{class, wxDataObject, root, [], []}. + +{class, wxFileDataObject, wxDataObject, [], + ['wxFileDataObject', 'AddFile','GetFilenames']}. +{class, wxTextDataObject, wxDataObject, [], + ['wxTextDataObject', 'GetTextLength', 'GetText', 'SetText']}. +{class, wxBitmapDataObject, wxDataObject, [], + [{'wxBitmapDataObject',1}, 'GetBitmap','SetBitmap']}. + +{class, wxClipboard, object, [], + ['wxClipboard','~wxClipboard','AddData','Clear','Close', + 'Flush','GetData','IsOpened', + 'Open','SetData','UsePrimarySelection' + , {'IsSupported', [{"format", [{type, "wxDataFormatId"}, {single,true}]}]}, + 'Get' + ]}. + +{class, wxSpinEvent, wxNotifyEvent, + [{acc, [{m_commandInt, "GetPosition()"}]}, + {event, [wxEVT_COMMAND_SPINCTRL_UPDATED, + {wxEVT_SPIN_UP, wxEVT_SCROLL_LINEUP, wxScrollEvent}, + {wxEVT_SPIN_DOWN, wxEVT_SCROLL_LINEDOWN, wxScrollEvent}, + {wxEVT_SPIN, wxEVT_SCROLL_THUMBTRACK, wxScrollEvent} + ]}], + ['GetPosition', 'SetPosition']}. + +{class, wxSplitterWindow, wxWindow, [], + [ + 'wxSplitterWindow', '~wxSplitterWindow', 'Create', 'GetMinimumPaneSize', 'GetSashGravity', + 'GetSashPosition', 'GetSplitMode', 'GetWindow1', 'GetWindow2', 'Initialize', 'IsSplit', + %% 'OnDoubleClickSash', 'OnUnsplit', 'OnSashPositionChange', + 'ReplaceWindow', 'SetSashGravity', 'SetSashPosition', 'SetSashSize', 'SetMinimumPaneSize', + 'SetSplitMode', 'SplitHorizontally', 'SplitVertically', 'Unsplit', 'UpdateSize' + ]}. + + +{class, wxSplitterEvent, wxNotifyEvent, + [ + {event, + [wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED, + wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING, + wxEVT_COMMAND_SPLITTER_DOUBLECLICKED, + wxEVT_COMMAND_SPLITTER_UNSPLIT + ]}], + ['GetSashPosition', 'GetX', 'GetY', + 'GetWindowBeingRemoved', 'SetSashPosition' + ]}. + + +{class, wxHtmlWindow, wxScrolledWindow, [], + [ + 'wxHtmlWindow',%'AddFilter', + 'AppendToPage', + %%'GetInternalRepresentation', + 'GetOpenedAnchor', + 'GetOpenedPage','GetOpenedPageTitle','GetRelatedFrame', + 'HistoryBack', 'HistoryCanBack','HistoryCanForward','HistoryClear','HistoryForward', + 'LoadFile','LoadPage', + %%'OnCellClicked','OnCellMouseHover','OnLinkClicked',OnOpeningURL, OnSetTitle + %'ReadCustomization', + 'SelectAll','SelectionToText','SelectLine','SelectWord', + 'SetBorders','SetFonts','SetPage','SetRelatedFrame','SetRelatedStatusBar', + 'ToText' + %%'WriteCustomization' + ]}. + + +{class, wxHtmlLinkEvent, wxCommandEvent, + [{acc, [{m_linkInfo, "GetLinkInfo()"}]}, + {event, [wxEVT_COMMAND_HTML_LINK_CLICKED]}], + ['GetLinkInfo']}. + +%% New No wxAuiToolBar yet..add when documentation exists +%% {class, wxAuiToolBarEvent, wxNotifyEvent, +%% [{acc, [{is_dropdown_clicked, "IsDropDownClicked()"}, +%% {click_pt, "GetClickPoint()"}, +%% {rect, "GetItemRect()"}, +%% {tool_id, "GetToolId()"}]}, +%% {event, [wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN, +%% wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK, +%% wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK, +%% wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG +%% ]}], +%% ['IsDropDownClicked', 'SetDropDownClicked', 'SetClickPoint', +%% 'GetItemRect', 'SetItemRect', 'GetToolId', 'SetToolId' +%% ]}. + +{class, wxAuiNotebookEvent, wxNotifyEvent, + [{acc, [{old_selection, "GetOldSelection()"}, + {selection, "GetSelection()"}, + {drag_source, "GetDragSource()"}]}, + {event, [wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSE, + wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGED, + wxEVT_COMMAND_AUINOTEBOOK_PAGE_CHANGING, + wxEVT_COMMAND_AUINOTEBOOK_BUTTON, + wxEVT_COMMAND_AUINOTEBOOK_BEGIN_DRAG, + wxEVT_COMMAND_AUINOTEBOOK_END_DRAG, + wxEVT_COMMAND_AUINOTEBOOK_DRAG_MOTION, + wxEVT_COMMAND_AUINOTEBOOK_ALLOW_DND, + {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_DOWN, {test_if, "wxCHECK_VERSION(2,8,5)"}}, + {wxEVT_COMMAND_AUINOTEBOOK_TAB_MIDDLE_UP, {test_if, "wxCHECK_VERSION(2,8,5)"}}, + {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_DOWN, {test_if, "wxCHECK_VERSION(2,8,5)"}}, + {wxEVT_COMMAND_AUINOTEBOOK_TAB_RIGHT_UP, {test_if, "wxCHECK_VERSION(2,8,5)"}}, + {wxEVT_COMMAND_AUINOTEBOOK_PAGE_CLOSED, {test_if, "wxCHECK_VERSION(2,8,5)"}}, + {wxEVT_COMMAND_AUINOTEBOOK_DRAG_DONE, {test_if, "wxCHECK_VERSION(2,8,5)"}}, + {wxEVT_COMMAND_AUINOTEBOOK_BG_DCLICK, {test_if, "wxCHECK_VERSION(2,8,5)"}} + ]}], + ['SetSelection', 'GetSelection', 'SetOldSelection', 'GetOldSelection', + 'SetDragSource', 'GetDragSource' + ]}. + + +{class, wxAuiManagerEvent, wxEvent, + [{acc, [{button, "GetButton()"}, + {dc, "GetDC()"}, + {pane, "GetPane()"}, + {manager, "GetManager()"} + ]}, + {event, [wxEVT_AUI_PANE_BUTTON, + wxEVT_AUI_PANE_CLOSE, + wxEVT_AUI_PANE_MAXIMIZE, + wxEVT_AUI_PANE_RESTORE, + wxEVT_AUI_RENDER, + wxEVT_AUI_FIND_MANAGER + ]}], + [ + 'SetManager', 'GetManager','SetPane','GetPane','SetButton','GetButton', + 'SetDC', 'GetDC', 'Veto', 'GetVeto', 'SetCanVeto', 'CanVeto' + ]}. + +{class, wxLogNull, root, [], + [wxLogNull, '~wxLogNull']}. + |