DEFINITIONS
This source file includes following functions.
1 #-----------------------------
2 # olegen.rb
3 # $Date: 2002/06/01 12:34:29 $
4 # $Revision: 1.1 $
5 #-----------------------------
6
7 require 'win32ole'
8
9 class WIN32COMGen
10 def initialize(typelib)
11 @typelib = typelib
12 @reciever = ""
13 end
14 attr_reader :typelib
15
16 def ole_classes(typelib)
17 begin
18 @ole = WIN32OLE.new(typelib)
19 [@ole.ole_obj_help]
20 rescue
21 WIN32OLE_TYPE.ole_classes(typelib)
22 end
23 end
24
25 def generate_args(method)
26 args = []
27 if method.size_opt_params >= 0
28 size_required_params = method.size_params - method.size_opt_params
29 else
30 size_required_params = method.size_params - 1
31 end
32 size_required_params.times do |i|
33 if method.params[i] && method.params[i].optional?
34 args.push "arg#{i}=nil"
35 else
36 args.push "arg#{i}"
37 end
38 end
39 if method.size_opt_params >= 0
40 method.size_opt_params.times do |i|
41 args.push "arg#{i + size_required_params}=nil"
42 end
43 else
44 args.push "*arg"
45 end
46 args.join(", ")
47 end
48
49 def generate_argtype(typedetails)
50 ts = ''
51 typedetails.each do |t|
52 case t
53 when 'CARRAY', 'VOID', 'UINT', 'RESULT', 'DECIMAL', 'I8', 'UI8'
54 # raise "Sorry type\"" + t + "\" not supported"
55 ts << "\"??? NOT SUPPORTED TYPE:`#{t}'\""
56 when 'USERDEFINED', 'Unknown Type 9'
57 ts << 'VT_DISPATCH'
58 break;
59 when 'SAFEARRAY'
60 ts << 'VT_ARRAY|'
61 when 'PTR'
62 ts << 'VT_BYREF|'
63 when 'INT'
64 ts << 'VT_I4'
65 else
66 if String === t
67 ts << 'VT_' + t
68 end
69 end
70 end
71 if ts.empty?
72 ts = 'VT_VARIANT'
73 elsif ts[-1] == ?|
74 ts += 'VT_VARIANT'
75 end
76 ts
77 end
78
79 def generate_argtypes(method, proptypes)
80 types = method.params.collect{|param|
81 generate_argtype(param.ole_type_detail)
82 }.join(", ")
83 if proptypes
84 types += ", " if types.size > 0
85 types += generate_argtype(proptypes)
86 end
87 types
88 end
89
90 def generate_method_body(method, disptype, types=nil)
91 " ret = #{@reciever}#{disptype}(#{method.dispid}, [" +
92 generate_args(method).gsub("=nil", "") +
93 "], [" +
94 generate_argtypes(method, types) +
95 "])\n" +
96 " @lastargs = WIN32OLE::ARGV\n" +
97 " ret"
98 end
99
100 def generate_method_help(method, type = nil)
101 str = " # "
102 if type
103 str += type
104 else
105 str += method.return_type
106 end
107 str += " #{method.name}"
108 if method.event?
109 str += " EVENT"
110 str += " in #{method.event_interface}"
111 end
112 if method.helpstring && method.helpstring != ""
113 str += "\n # "
114 str += method.helpstring
115 end
116 args_help = generate_method_args_help(method)
117 if args_help
118 str += "\n"
119 str += args_help
120 end
121 str
122 end
123
124 def generate_method_args_help(method)
125 args = []
126 method.params.each_with_index {|param, i|
127 h = " # #{param.ole_type} arg#{i} --- #{param.name}"
128 inout = []
129 inout.push "IN" if param.input?
130 inout.push "OUT" if param.output?
131 h += " [#{inout.join('/')}]"
132 h += " ( = #{param.default})" if param.default
133 args.push h
134 }
135 if args.size > 0
136 args.join("\n")
137 else
138 nil
139 end
140 end
141
142 def generate_method(method, disptype, io = STDOUT, types = nil)
143 io.puts "\n"
144 io.puts generate_method_help(method)
145 if method.invoke_kind == 'PROPERTYPUT'
146 io.print " def #{method.name}=("
147 else
148 io.print " def #{method.name}("
149 end
150 io.print generate_args(method)
151 io.puts ")"
152 io.puts generate_method_body(method, disptype, types)
153 io.puts " end"
154 end
155
156 def generate_propputref_methods(klass, io = STDOUT)
157 klass.ole_methods.select {|method|
158 method.invoke_kind == 'PROPERTYPUTREF' && method.visible?
159 }.each do |method|
160 generate_method(method, io)
161 end
162 end
163
164 def generate_properties_with_args(klass, io = STDOUT)
165 klass.ole_methods.select {|method|
166 method.invoke_kind == 'PROPERTYGET' &&
167 method.visible? &&
168 method.size_params > 0
169 }.each do |method|
170 types = method.return_type_detail
171 io.puts "\n"
172 io.puts generate_method_help(method, types[0])
173 io.puts " def #{method.name}"
174 if klass.ole_type == "Class"
175 io.print " OLEProperty.new(@dispatch, #{method.dispid}, ["
176 else
177 io.print " OLEProperty.new(self, #{method.dispid}, ["
178 end
179 io.print generate_argtypes(method, nil)
180 io.print "], ["
181 io.print generate_argtypes(method, types)
182 io.puts "])"
183 io.puts " end"
184 end
185 end
186
187 def generate_propput_methods(klass, io = STDOUT)
188 klass.ole_methods.select {|method|
189 method.invoke_kind == 'PROPERTYPUT' && method.visible? &&
190 method.size_params == 1
191 }.each do |method|
192 ms = klass.ole_methods.select {|m|
193 m.invoke_kind == 'PROPERTYGET' &&
194 m.dispid == method.dispid
195 }
196 types = []
197 if ms.size == 1
198 types = ms[0].return_type_detail
199 end
200 generate_method(method, '_setproperty', io, types)
201 end
202 end
203
204 def generate_propget_methods(klass, io = STDOUT)
205 klass.ole_methods.select {|method|
206 method.invoke_kind == 'PROPERTYGET' && method.visible? &&
207 method.size_params == 0
208 }.each do |method|
209 generate_method(method, '_getproperty', io)
210 end
211 end
212
213 def generate_func_methods(klass, io = STDOUT)
214 klass.ole_methods.select {|method|
215 method.invoke_kind == "FUNC" && method.visible?
216 }.each do |method|
217 generate_method(method, '_invoke', io)
218 end
219 end
220
221 def generate_methods(klass, io = STDOUT)
222 generate_propget_methods(klass, io)
223 generate_propput_methods(klass, io)
224 generate_properties_with_args(klass, io)
225 generate_func_methods(klass, io)
226 # generate_propputref_methods(klass, io)
227 end
228
229 def generate_constants(klass, io = STDOUT)
230 klass.variables.select {|v|
231 v.visible? && v.variable_kind == 'CONSTANT'
232 }.each do |v|
233 io.print " "
234 io.print v.name.sub(/^./){|c| c.upcase}
235 io.print " = "
236 io.puts v.value
237 end
238 end
239
240 def class_name(klass)
241 klass_name = klass.name
242 if klass.ole_type == "Class" &&
243 klass.guid &&
244 klass.progid
245 klass_name = klass.progid.gsub(/\./, '_')
246 end
247 if /^[A-Z]/ !~ klass_name || Module.constants.include?(klass_name)
248 klass_name = 'OLE' + klass_name
249 end
250 klass_name
251 end
252
253 def define_initialize(klass)
254 <<STR
255
256 def initialize(obj = nil)
257 @clsid = "#{klass.guid}"
258 @progid = "#{klass.progid}"
259 if obj.nil?
260 @dispatch = WIN32OLE.new @progid
261 else
262 @dispatch = obj
263 end
264 end
265 STR
266 end
267
268 def define_include
269 " include WIN32OLE::VARIANT"
270 end
271
272 def define_instance_variables
273 " attr_reader :lastargs"
274 end
275
276 def define_method_missing
277 <<STR
278
279 def method_missing(cmd, *arg)
280 @dispatch.method_missing(cmd, *arg)
281 end
282 STR
283 end
284
285 def define_class(klass, io = STDOUT)
286 io.puts "class #{class_name(klass)} # #{klass.name}"
287 io.puts define_include
288 io.puts define_instance_variables
289 io.puts " attr_reader :dispatch"
290 io.puts " attr_reader :clsid"
291 io.puts " attr_reader :progid"
292 io.puts define_initialize(klass)
293 io.puts define_method_missing
294 end
295
296 def define_module(klass, io = STDOUT)
297 io.puts "module #{class_name(klass)}"
298 io.puts define_include
299 io.puts define_instance_variables
300 end
301
302 def generate_class(klass, io = STDOUT)
303 io.puts "\n# #{klass.helpstring}"
304 if klass.ole_type == "Class" &&
305 klass.guid &&
306 klass.progid
307 @reciever = "@dispatch."
308 define_class(klass, io)
309 else
310 @reciever = ""
311 define_module(klass, io)
312 end
313 generate_constants(klass, io)
314 generate_methods(klass, io)
315 io.puts "end"
316 end
317
318 def generate(io = STDOUT)
319 io.puts "require 'win32ole'"
320 io.puts "require 'win32ole/property'"
321
322 ole_classes(typelib).select{|klass|
323 klass.visible? &&
324 (klass.ole_type == "Class" ||
325 klass.ole_type == "Interface" ||
326 klass.ole_type == "Dispatch" ||
327 klass.ole_type == "Enum")
328 }.each do |klass|
329 generate_class(klass, io)
330 end
331 begin
332 @ole.quit if @ole
333 rescue
334 end
335 end
336 end
337
338 require 'win32ole'
339 if __FILE__ == $0
340 if ARGV.size == 0
341 $stderr.puts "usage: #{$0} Type Library [...]"
342 exit 1
343 end
344 ARGV.each do |typelib|
345 comgen = WIN32COMGen.new(typelib)
346 comgen.generate
347 end
348 end