# frozen_string_literal: false #----------------------------- # olegen.rb # $Revision$ #----------------------------- require "win32ole" class WIN32COMGen def initialize(typelib) @typelib = typelib @receiver = "" end attr_reader :typelib def ole_classes(typelib) @ole = WIN32OLE.new(typelib) [@ole.ole_obj_help] rescue WIN32OLE_TYPE.ole_classes(typelib) end def generate_args(method) args = [] size_required_params = if method.size_opt_params >= 0 method.size_params - method.size_opt_params else method.size_params - 1 end size_required_params.times do |i| if method.params[i] && method.params[i].optional? args.push "arg#{i}=nil" else args.push "arg#{i}" end end if method.size_opt_params >= 0 method.size_opt_params.times do |i| args.push "arg#{i + size_required_params}=nil" end else args.push "*arg" end args.join(", ") end def generate_argtype(typedetails) ts = "" typedetails.each do |t| case t when "CARRAY", "VOID", "UINT", "RESULT", "DECIMAL", "I8", "UI8" # raise "Sorry type\"" + t + "\" not supported" ts << "\"??? NOT SUPPORTED TYPE:`#{t}'\"" when "USERDEFINED", "Unknown Type 9" ts << "VT_DISPATCH" break when "SAFEARRAY" ts << "VT_ARRAY|" when "PTR" ts << "VT_BYREF|" when "INT" ts << "VT_I4" else if String === t ts << "VT_" + t end end end if ts.empty? ts = "VT_VARIANT" elsif ts.end_with?("|") ts += "VT_VARIANT" end ts end def generate_argtypes(method, proptypes) types = method.params.collect { |param| generate_argtype(param.ole_type_detail) }.join(", ") if proptypes types += ", " if types.size > 0 types += generate_argtype(proptypes) end types end def generate_method_body(method, disptype, types = nil) " ret = #{@receiver}#{disptype}(#{method.dispid}, [" + generate_args(method).gsub("=nil", "") + "], [" + generate_argtypes(method, types) + "])\n" + " @lastargs = WIN32OLE::ARGV\n" + " ret" end def generate_method_help(method, type = nil) str = " # " str += type || method.return_type str += " #{method.name}" if method.event? str += " EVENT" str += " in #{method.event_interface}" end if method.helpstring && method.helpstring != "" str += "\n # " str += method.helpstring end args_help = generate_method_args_help(method) if args_help str += "\n" str += args_help end str end def generate_method_args_help(method) args = [] method.params.each_with_index { |param, i| h = " # #{param.ole_type} arg#{i} --- #{param.name}" inout = [] inout.push "IN" if param.input? inout.push "OUT" if param.output? h += " [#{inout.join("/")}]" h += " ( = #{param.default})" if param.default args.push h } if args.size > 0 args.join("\n") end end def generate_method(method, disptype, io = STDOUT, types = nil) io.puts "\n" io.puts generate_method_help(method) if method.invoke_kind == "PROPERTYPUT" io.print " def #{method.name}=(" else io.print " def #{method.name}(" end io.print generate_args(method) io.puts ")" io.puts generate_method_body(method, disptype, types) io.puts " end" end def generate_propputref_methods(klass, io = STDOUT) klass.ole_methods.select { |method| method.invoke_kind == "PROPERTYPUTREF" && method.visible? }.each do |method| generate_method(method, io) end end def generate_properties_with_args(klass, io = STDOUT) klass.ole_methods.select { |method| method.invoke_kind == "PROPERTYGET" && method.visible? && method.size_params > 0 }.each do |method| types = method.return_type_detail io.puts "\n" io.puts generate_method_help(method, types[0]) io.puts " def #{method.name}" if klass.ole_type == "Class" io.print " OLEProperty.new(@dispatch, #{method.dispid}, [" else io.print " OLEProperty.new(self, #{method.dispid}, [" end io.print generate_argtypes(method, nil) io.print "], [" io.print generate_argtypes(method, types) io.puts "])" io.puts " end" end end def generate_propput_methods(klass, io = STDOUT) klass.ole_methods.select { |method| method.invoke_kind == "PROPERTYPUT" && method.visible? && method.size_params == 1 }.each do |method| ms = klass.ole_methods.select { |m| m.invoke_kind == "PROPERTYGET" && m.dispid == method.dispid } types = [] if ms.size == 1 types = ms[0].return_type_detail end generate_method(method, "_setproperty", io, types) end end def generate_propget_methods(klass, io = STDOUT) klass.ole_methods.select { |method| method.invoke_kind == "PROPERTYGET" && method.visible? && method.size_params == 0 }.each do |method| generate_method(method, "_getproperty", io) end end def generate_func_methods(klass, io = STDOUT) klass.ole_methods.select { |method| method.invoke_kind == "FUNC" && method.visible? }.each do |method| generate_method(method, "_invoke", io) end end def generate_methods(klass, io = STDOUT) generate_propget_methods(klass, io) generate_propput_methods(klass, io) generate_properties_with_args(klass, io) generate_func_methods(klass, io) # generate_propputref_methods(klass, io) end def generate_constants(klass, io = STDOUT) klass.variables.select { |v| v.visible? && v.variable_kind == "CONSTANT" }.each do |v| io.print " " io.print v.name.sub(/^./) { $&.upcase } io.print " = " io.puts v.value end end def class_name(klass) klass_name = klass.name if klass.ole_type == "Class" && klass.guid && klass.progid klass_name = klass.progid.tr(".", "_") end if /^[A-Z]/ !~ klass_name || Module.constants.include?(klass_name) klass_name = "OLE" + klass_name end klass_name end def define_initialize(klass) <