[macruby-changes] [312] MacRuby/branches/testing

source_changes at macosforge.org source_changes at macosforge.org
Sun Jul 6 15:18:19 PDT 2008


Revision: 312
          http://trac.macosforge.org/projects/ruby/changeset/312
Author:   lsansonetti at apple.com
Date:     2008-07-06 15:18:19 -0700 (Sun, 06 Jul 2008)
Log Message:
-----------
merge from trunk

Modified Paths:
--------------
    MacRuby/branches/testing/Rakefile
    MacRuby/branches/testing/class.c
    MacRuby/branches/testing/instruby.rb
    MacRuby/branches/testing/objc.m
    MacRuby/branches/testing/test/ruby/test_objc.rb
    MacRuby/branches/testing/vm.c
    MacRuby/branches/testing/vm_eval.c
    MacRuby/branches/testing/vm_insnhelper.c

Added Paths:
-----------
    MacRuby/branches/testing/lib/osx/
    MacRuby/branches/testing/lib/osx/cocoa.rb
    MacRuby/branches/testing/lib/osx/rubycocoa.rb
    MacRuby/branches/testing/sample-macruby/RubyCocoa/
    MacRuby/branches/testing/sample-macruby/RubyCocoa/HelloWorld.rb
    MacRuby/branches/testing/sample-macruby/RubyCocoa/README
    MacRuby/branches/testing/sample-macruby/RubyCocoa/TransparentHello.rb
    MacRuby/branches/testing/sample-macruby/RubyCocoa/darkroom.rb
    MacRuby/branches/testing/sample-macruby/RubyCocoa/fontnames.rb
    MacRuby/branches/testing/sample-macruby/RubyCocoa/sndplay.rb
    MacRuby/branches/testing/test-macruby/rubycocoa_test.rb

Removed Paths:
-------------
    MacRuby/branches/testing/lib/osx/cocoa.rb
    MacRuby/branches/testing/lib/osx/rubycocoa.rb
    MacRuby/branches/testing/sample-macruby/RubyCocoa/HelloWorld.rb
    MacRuby/branches/testing/sample-macruby/RubyCocoa/README
    MacRuby/branches/testing/sample-macruby/RubyCocoa/TransparentHello.rb
    MacRuby/branches/testing/sample-macruby/RubyCocoa/darkroom.rb
    MacRuby/branches/testing/sample-macruby/RubyCocoa/fontnames.rb
    MacRuby/branches/testing/sample-macruby/RubyCocoa/sndplay.rb

Modified: MacRuby/branches/testing/Rakefile
===================================================================
--- MacRuby/branches/testing/Rakefile	2008-07-06 22:09:00 UTC (rev 311)
+++ MacRuby/branches/testing/Rakefile	2008-07-06 22:18:19 UTC (rev 312)
@@ -1,12 +1,29 @@
 # User customizable variables.
 
-RUBY_INSTALL_NAME = 'macruby'
-RUBY_SO_NAME = RUBY_INSTALL_NAME
-ARCHS = %w{ppc i386}
-FRAMEWORK_NAME = 'MacRuby'
-FRAMEWORK_INSTDIR = '/Library/Frameworks'
-NO_WARN_BUILD = true
+def do_option(name, default)
+  val = ENV[name]
+  if val
+    if block_given?
+      yield val
+    else
+      val
+    end
+  else
+    default
+  end
+end
 
+RUBY_INSTALL_NAME = do_option('ruby_install_name', 'macruby')
+RUBY_SO_NAME = do_option('ruby_so_name', RUBY_INSTALL_NAME)
+ARCHS = do_option('archs', %w{ppc i386}) { |x| x.split(',') }
+FRAMEWORK_NAME = do_option('framework_name', 'MacRuby')
+FRAMEWORK_INSTDIR = do_option('framework_instdir', '/Library/Frameworks')
+NO_WARN_BUILD = !do_option('allow_build_warnings', false)
+BUILD_AS_EMBEDDABLE = do_option('build_as_embeddable', false)
+ENABLE_STATIC_LIBRARY = do_option('enable_static_library', 'no') { 'yes' }
+
+# TODO: we should find a way to document these options in rake's --help
+
 # Everything below this comment should *not* be customized.
 
 version_h = File.read('version.h')
@@ -30,12 +47,21 @@
 RUBY_VENDOR_LIB2 = File.join(RUBY_VENDOR_LIB, NEW_RUBY_VERSION)
 RUBY_VENDOR_ARCHLIB = File.join(RUBY_VENDOR_LIB2, NEW_RUBY_PLATFORM)
 
+INSTALL_NAME = 
+  if BUILD_AS_EMBEDDABLE
+    File.join("@executable_path/../Frameworks", FRAMEWORK_NAME + '.framework',
+	      'Versions', MACRUBY_VERSION, 'usr/lib', 
+	      'lib' + RUBY_SO_NAME + '.dylib')
+  else
+    File.join(FRAMEWORK_USR_LIB, 'lib' + RUBY_SO_NAME + '.dylib')
+  end
+
 ARCHFLAGS = ARCHS.map { |a| '-arch ' + a }.join(' ')
 CFLAGS = "-I. -I./include -I/usr/include/libxml2 #{ARCHFLAGS} -fno-common -pipe -O2 -g -Wall"
 CFLAGS << " -Wno-parentheses -Wno-deprecated-declarations -Werror" if NO_WARN_BUILD
 OBJC_CFLAGS = CFLAGS + " -fobjc-gc-only"
 LDFLAGS = "-lpthread -ldl -lxml2 -lobjc -lffi -lauto -framework Foundation"
-DLDFLAGS = "-dynamiclib -undefined suppress -flat_namespace -install_name #{File.join(FRAMEWORK_USR_LIB, 'lib' + RUBY_SO_NAME + '.dylib')} -current_version #{MACRUBY_VERSION} -compatibility_version #{MACRUBY_VERSION}"
+DLDFLAGS = "-dynamiclib -undefined suppress -flat_namespace -install_name #{INSTALL_NAME} -current_version #{MACRUBY_VERSION} -compatibility_version #{MACRUBY_VERSION}"
 
 OBJS = %w{ 
   array bignum class compar complex dir enum enumerator error eval load proc 
@@ -388,6 +414,7 @@
   CONFIG["SOLIBS"] = ""
   CONFIG["DLDLIBS"] = ""
   CONFIG["ENABLE_SHARED"] = "yes"
+  CONFIG["ENABLE_STATIC"] = "#{ENABLE_STATIC_LIBRARY}"
   CONFIG["MAINLIBS"] = ""
   CONFIG["COMMON_LIBS"] = ""
   CONFIG["COMMON_MACROS"] = ""
@@ -550,6 +577,34 @@
   end
 end
 
+namespace :rubycocoa do
+  def get(url)
+    file = File.basename(url)
+    sh "curl #{url} -o /tmp/#{file}"
+    # for some reason mocha extracts with some junk...
+    puts `cd /tmp && tar -zxvf #{file}`
+  end
+  
+  def install(path)
+    cp_r path, '/Library/Frameworks/MacRuby.framework/Versions/Current/usr/lib/ruby/site_ruby/'
+  end
+  
+  desc 'For lack of working RubyGems this is a task that installs the dependencies for the RubyCocoa layer tests'
+  task :install_test_spec_and_mocha do
+    get 'http://files.rubyforge.vm.bytemark.co.uk/test-spec/test-spec-0.4.0.tar.gz'
+    install '/tmp/test-spec-0.4.0/lib/test'
+    
+    get 'http://files.rubyforge.mmmultiworks.com/mocha/mocha-0.5.6.tgz'
+    mocha = '/tmp/mocha-0.5.6'
+    FileList["#{mocha}/lib/*.rb", "#{mocha}/lib/mocha"].each { |f| install f }
+  end
+  
+  desc 'Run the RubyCocoa layer tests'
+  task :test do
+    sh 'macruby test-macruby/rubycocoa_test.rb'
+  end
+end
+
 desc "Same as framework:install"
 task :install => 'framework:install'
 

Modified: MacRuby/branches/testing/class.c
===================================================================
--- MacRuby/branches/testing/class.c	2008-07-06 22:09:00 UTC (rev 311)
+++ MacRuby/branches/testing/class.c	2008-07-06 22:18:19 UTC (rev 312)
@@ -130,17 +130,24 @@
 }
 
 static VALUE
-rb_objc_alloc_class(const char *name, VALUE super, VALUE flags, VALUE klass)
+rb_objc_alloc_class(const char *name, VALUE *psuper, VALUE flags, VALUE klass)
 {
-    VALUE obj;
+    VALUE super, obj;
     Class ocklass, ocsuper;
     char ocname[128];
 
+    super = psuper == NULL ? 0 : *psuper;
+
     if (name == NULL) {
 	static long anon_count = 1;
     	snprintf(ocname, sizeof ocname, "RBAnonymous%ld", ++anon_count);
     }
     else {
+	if (super == rb_cBasicObject && strcmp(name, "Object") != 0) {
+	    rb_warn("Do not subclass NSObject directly, please subclass " \
+		    "Object instead.");
+	    super = *psuper = rb_cObject; 
+	}
 	if (objc_getClass(name) != NULL) {
 	    long count = 1;
 	    snprintf(ocname, sizeof ocname, "RB%s", name);
@@ -183,7 +190,7 @@
 {
     VALUE klass;
     
-    klass = rb_objc_alloc_class(name, super, T_CLASS, rb_cClass);
+    klass = rb_objc_alloc_class(name, &super, T_CLASS, rb_cClass);
  
     class_init(klass);
 
@@ -247,7 +254,7 @@
 class_alloc(VALUE flags, VALUE klass)
 {
 #if WITH_OBJC
-    VALUE obj = rb_objc_alloc_class(NULL, 0, flags, klass);
+    VALUE obj = rb_objc_alloc_class(NULL, NULL, flags, klass);
 #else
     NEWOBJ(obj, struct RClass);
     OBJSETUP(obj, klass, flags);

Modified: MacRuby/branches/testing/instruby.rb
===================================================================
--- MacRuby/branches/testing/instruby.rb	2008-07-06 22:09:00 UTC (rev 311)
+++ MacRuby/branches/testing/instruby.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -221,6 +221,7 @@
 mandir = File.join(CONFIG["mandir"], "man")
 configure_args = Shellwords.shellwords(CONFIG["configure_args"])
 enable_shared = CONFIG["ENABLE_SHARED"] == 'yes'
+enable_static = CONFIG["ENABLE_STATIC"] == 'yes'
 dll = CONFIG["LIBRUBY_SO"]
 lib = CONFIG["LIBRUBY"]
 arc = CONFIG["LIBRUBY_A"]
@@ -241,7 +242,7 @@
     install dll, bindir, :mode => $prog_mode
   end
   install lib, libdir, :mode => $prog_mode unless lib == arc
-  install arc, libdir, :mode => $data_mode
+  install arc, libdir, :mode => $data_mode if enable_static
   install "rbconfig.rb", archlibdir, :mode => $data_mode
   if CONFIG["ARCHFILE"]
     for file in CONFIG["ARCHFILE"].split
@@ -435,6 +436,8 @@
 
 install_stuff('Xcode templates', 'misc/xcode-templates', 
   '/Library/Application Support/Developer/3.0/Xcode', 0755)
+install_stuff('Xcode 3.1 templates', 'misc/xcode-templates', 
+  '/Library/Application Support/Developer/Shared/Xcode', 0755)
 install_stuff('samples', 'sample-macruby', 
   '/Developer/Examples/Ruby/MacRuby', 0775)
 

Copied: MacRuby/branches/testing/lib/osx (from rev 311, MacRuby/trunk/lib/osx)

Deleted: MacRuby/branches/testing/lib/osx/cocoa.rb
===================================================================
--- MacRuby/trunk/lib/osx/cocoa.rb	2008-07-06 22:09:00 UTC (rev 311)
+++ MacRuby/branches/testing/lib/osx/cocoa.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -1,2 +0,0 @@
-Kernel.framework 'AppKit'
-require File.expand_path('../rubycocoa', __FILE__)
\ No newline at end of file

Copied: MacRuby/branches/testing/lib/osx/cocoa.rb (from rev 311, MacRuby/trunk/lib/osx/cocoa.rb)
===================================================================
--- MacRuby/branches/testing/lib/osx/cocoa.rb	                        (rev 0)
+++ MacRuby/branches/testing/lib/osx/cocoa.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -0,0 +1,2 @@
+Kernel.framework 'AppKit'
+require File.expand_path('../rubycocoa', __FILE__)
\ No newline at end of file

Deleted: MacRuby/branches/testing/lib/osx/rubycocoa.rb
===================================================================
--- MacRuby/trunk/lib/osx/rubycocoa.rb	2008-07-06 22:09:00 UTC (rev 311)
+++ MacRuby/branches/testing/lib/osx/rubycocoa.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -1,93 +0,0 @@
-#!/usr/bin/env macruby
-
-module Kernel
-  class << self
-    alias_method :__framework_before_rubycocoa_layer, :framework
-    def framework(f)
-      $LOADING_FRAMEWORK = true
-      __framework_before_rubycocoa_layer(f)
-      $LOADING_FRAMEWORK = false
-    end
-  end
-end
-
-class NSObject
-  class << self
-    alias_method :ib_outlets, :ib_outlet
-    
-    alias_method :__method_added_before_rubycocoa_layer, :method_added
-    def method_added(mname)
-      unless $LOADING_FRAMEWORK
-        mname_str = mname.to_s
-        unless mname_str =~ /^__|\s/
-          parts = mname_str.split('_')
-          if parts.length > 1 and parts.length == instance_method(mname).arity
-            class_eval { alias_method (parts.join(':') << ':').to_sym, mname }
-            return
-          end
-        end
-      end
-      __method_added_before_rubycocoa_layer(mname)
-    end
-  end
-  
-  def objc_send(*args)
-    if args.length > 1
-      selector, new_args = '', []
-      (args.length / 2).times do
-        selector << "#{args.shift}:"
-        new_args << args.shift
-      end
-      send(selector, *new_args)
-    else
-      send(args.first)
-    end
-  end
-  
-  alias_method :__method_missing_before_rubycocoa_layer, :method_missing
-  def method_missing(mname, *args, &block)
-    if (parts = mname.to_s.split('_')).length > 1
-       if parts.first == 'super'
-         selector = args.empty? ? parts.last : parts[1..-1].join(':') << ':'
-         if self.class.superclass.instance_methods.include?(selector.to_sym)
-	   return __super_objc_send__(selector, *args)
-         end
-       end
-      
-      selector = parts.join(':') << ':'
-      if respond_to?(selector) || respondsToSelector(selector) == 1
-        eval "def #{mname}(*args); send('#{selector}', *args); end"
-        return send(selector, *args)
-      end
-    end
-    # FIXME: For some reason calling super or the original implementation
-    # causes a stack level too deep execption. Is this a problem?
-    #__method_missing_before_rubycocoa_layer(mname, *args, &block)
-    
-    raise NoMethodError, "undefined method `#{mname}' for #{inspect}:#{self.class}"
-  end
-end
-
-module OSX
-  class << self
-    def require_framework(framework)
-      Kernel.framework(framework)
-    end
-    
-    def method_missing(mname, *args)
-      if Kernel.respond_to? mname
-        module_eval "def #{mname}(*args); Kernel.send(:#{mname}, *args); end"
-        Kernel.send(mname, *args)
-      else
-        super
-      end
-    end
-    
-    def const_missing(constant)
-      Object.const_get(constant)
-    rescue NameError
-      super
-    end
-  end
-end
-include OSX

Copied: MacRuby/branches/testing/lib/osx/rubycocoa.rb (from rev 311, MacRuby/trunk/lib/osx/rubycocoa.rb)
===================================================================
--- MacRuby/branches/testing/lib/osx/rubycocoa.rb	                        (rev 0)
+++ MacRuby/branches/testing/lib/osx/rubycocoa.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -0,0 +1,93 @@
+#!/usr/bin/env macruby
+
+module Kernel
+  class << self
+    alias_method :__framework_before_rubycocoa_layer, :framework
+    def framework(f)
+      $LOADING_FRAMEWORK = true
+      __framework_before_rubycocoa_layer(f)
+      $LOADING_FRAMEWORK = false
+    end
+  end
+end
+
+class NSObject
+  class << self
+    alias_method :ib_outlets, :ib_outlet
+    
+    alias_method :__method_added_before_rubycocoa_layer, :method_added
+    def method_added(mname)
+      unless $LOADING_FRAMEWORK
+        mname_str = mname.to_s
+        unless mname_str =~ /^__|\s/
+          parts = mname_str.split('_')
+          if parts.length > 1 and parts.length == instance_method(mname).arity
+            class_eval { alias_method (parts.join(':') << ':').to_sym, mname }
+            return
+          end
+        end
+      end
+      __method_added_before_rubycocoa_layer(mname)
+    end
+  end
+  
+  def objc_send(*args)
+    if args.length > 1
+      selector, new_args = '', []
+      (args.length / 2).times do
+        selector << "#{args.shift}:"
+        new_args << args.shift
+      end
+      send(selector, *new_args)
+    else
+      send(args.first)
+    end
+  end
+  
+  alias_method :__method_missing_before_rubycocoa_layer, :method_missing
+  def method_missing(mname, *args, &block)
+    if (parts = mname.to_s.split('_')).length > 1
+       if parts.first == 'super'
+         selector = args.empty? ? parts.last : parts[1..-1].join(':') << ':'
+         if self.class.superclass.instance_methods.include?(selector.to_sym)
+	   return __super_objc_send__(selector, *args)
+         end
+       end
+      
+      selector = parts.join(':') << ':'
+      if respond_to?(selector) || respondsToSelector(selector) == 1
+        eval "def #{mname}(*args); send('#{selector}', *args); end"
+        return send(selector, *args)
+      end
+    end
+    # FIXME: For some reason calling super or the original implementation
+    # causes a stack level too deep execption. Is this a problem?
+    #__method_missing_before_rubycocoa_layer(mname, *args, &block)
+    
+    raise NoMethodError, "undefined method `#{mname}' for #{inspect}:#{self.class}"
+  end
+end
+
+module OSX
+  class << self
+    def require_framework(framework)
+      Kernel.framework(framework)
+    end
+    
+    def method_missing(mname, *args)
+      if Kernel.respond_to? mname
+        module_eval "def #{mname}(*args); Kernel.send(:#{mname}, *args); end"
+        Kernel.send(mname, *args)
+      else
+        super
+      end
+    end
+    
+    def const_missing(constant)
+      Object.const_get(constant)
+    rescue NameError
+      super
+    end
+  end
+end
+include OSX

Modified: MacRuby/branches/testing/objc.m
===================================================================
--- MacRuby/branches/testing/objc.m	2008-07-06 22:09:00 UTC (rev 311)
+++ MacRuby/branches/testing/objc.m	2008-07-06 22:18:19 UTC (rev 312)
@@ -163,7 +163,7 @@
 	    type++;
 	    buf[0] = _C_PTR;
 	    buf_len -= 1;
-	    return rb_objc_get_first_type(type, buf, buf_len);
+	    return rb_objc_get_first_type(type, &buf[1], buf_len);
     }
 
     type++;
@@ -402,7 +402,7 @@
 }
 
 static bool
-rb_objc_rval_to_ocid(VALUE rval, void **ocval)
+rb_objc_rval_to_ocid(VALUE rval, void **ocval, bool force_nsnil)
 {
     if (!rb_special_const_p(rval) && rb_objc_is_non_native(rval)) {
 	*(id *)ocval = (id)rval;
@@ -423,7 +423,15 @@
 	    return true;
 
 	case T_NIL:
-	    *(id *)ocval = NULL;
+	    if (force_nsnil) {
+		static id snull = nil;
+		if (snull == nil)
+		    snull = [NSNull null];
+		*(id *)ocval = snull;
+	    }
+	    else {
+		*(id *)ocval = NULL;
+	    }
 	    return true;
 
 	case T_TRUE:
@@ -710,7 +718,7 @@
     switch (*octype) {
 	case _C_ID:
 	case _C_CLASS:
-	    ok = rb_objc_rval_to_ocid(rval, ocval);
+	    ok = rb_objc_rval_to_ocid(rval, ocval, false);
 	    break;
 
 	case _C_SEL:
@@ -1063,47 +1071,21 @@
     Method method;
     ffi_cif *cif;
     IMP imp;
+    Class klass;
 };
 
 static VALUE
-rb_objc_to_ruby_closure(int argc, VALUE *argv, VALUE rcv)
+rb_objc_call_objc(int argc, VALUE *argv, id ocrcv, Class klass, 
+		  bool super_call, struct objc_ruby_closure_context *ctx)
 {
     unsigned i, real_count, count;
     ffi_type *ffi_rettype, **ffi_argtypes;
     void *ffi_ret, **ffi_args;
     ffi_cif *cif;
-    Class klass;
     const char *type;
     char buf[128];
-    id ocrcv;
     void *imp;
-    struct objc_ruby_closure_context *ctx;
-    bool super_call;
 
-    super_call = (ruby_current_thread->cfp->flag >> FRAME_MAGIC_MASK_BITS) 
-	& VM_CALL_SUPER_BIT;
-
-    rb_objc_rval_to_ocid(rcv, (void **)&ocrcv);
-    klass = *(Class *)ocrcv;
-
-    assert(rb_current_cfunc_node != NULL);
-
-    if (rb_current_cfunc_node->u3.value == 0) {
-	ctx = (struct objc_ruby_closure_context *)xmalloc(sizeof(
-	    struct objc_ruby_closure_context));
-	ctx->selector = sel_registerName(rb_id2name(rb_frame_this_func()));
-	ctx->bs_method = rb_bs_find_method(klass, ctx->selector);
-	ctx->method = class_getInstanceMethod(klass, ctx->selector); 
-	ctx->cif = NULL;
-	ctx->imp = NULL;
-	assert(ctx->method != NULL);
-	GC_WB(&rb_current_cfunc_node->u3.value, ctx);
-    }
-    else {
-	ctx = (struct objc_ruby_closure_context *)
-	    rb_current_cfunc_node->u3.value;
-    }
-
     count = method_getNumberOfArguments(ctx->method);
     assert(count >= 2);
 
@@ -1127,7 +1109,7 @@
 		if (super_call) {
 		    struct objc_super s;
 		    s.receiver = ocrcv;
-		    s.class = class_getSuperclass(*(Class *)ocrcv);
+		    s.class = klass;
 		    ffi_ret = objc_msgSendSuper(&s, ctx->selector);
 		}
 		else {
@@ -1154,16 +1136,14 @@
     ffi_args[1] = &ctx->selector;
 
     if (super_call) {
-	Class sklass;
 	Method smethod;
-	sklass = class_getSuperclass(klass);
-	assert(sklass != NULL);
-	smethod = class_getInstanceMethod(sklass, ctx->selector);
+	smethod = class_getInstanceMethod(klass, ctx->selector);
 	assert(smethod != ctx->method);
-	imp = method_getImplementation(smethod);	
+	imp = method_getImplementation(smethod);
+	assert(imp != NULL);
     }
     else {
-	if (ctx->imp != NULL) {
+	if (ctx->imp != NULL && ctx->klass == klass) {
 	    imp = ctx->imp;
 	}
 	else {
@@ -1238,6 +1218,82 @@
     }
 }
 
+static VALUE
+rb_objc_to_ruby_closure(int argc, VALUE *argv, VALUE rcv)
+{
+    id ocrcv;
+    bool super_call;
+    Class klass;
+    struct objc_ruby_closure_context *ctx;
+
+    rb_objc_rval_to_ocid(rcv, (void **)&ocrcv, true);
+    super_call = (ruby_current_thread->cfp->flag >> FRAME_MAGIC_MASK_BITS) 
+	& VM_CALL_SUPER_BIT;
+    klass = super_call ? class_getSuperclass(*(Class *)ocrcv) : *(Class *)ocrcv;
+    
+    assert(rb_current_cfunc_node != NULL);
+
+    if (rb_current_cfunc_node->u3.value == 0) {
+	const char *selname;
+	size_t selnamelen;
+
+	ctx = (struct objc_ruby_closure_context *)xmalloc(sizeof(
+	    struct objc_ruby_closure_context));
+
+	selname = rb_id2name(rb_frame_this_func());
+	selnamelen = strlen(selname);
+	if (argc == 1 && selname[selnamelen - 1] != ':') {
+	    char *tmp = alloca(selnamelen + 2);
+	    snprintf(tmp, selnamelen + 2, "%s:", selname);
+	    selname = (const char *)tmp;
+	}
+	ctx->selector = sel_registerName(selname);
+
+	ctx->bs_method = rb_bs_find_method(*(Class *)rcv, ctx->selector);
+	ctx->method = class_getInstanceMethod(*(Class *)rcv, ctx->selector); 
+	assert(ctx->method != NULL);
+	ctx->cif = NULL;
+	ctx->imp = NULL;
+	ctx->klass = NULL;
+	GC_WB(&rb_current_cfunc_node->u3.value, ctx);
+    }
+    else {
+	ctx = (struct objc_ruby_closure_context *)
+	    rb_current_cfunc_node->u3.value;
+    }
+
+    return rb_objc_call_objc(argc, argv, ocrcv, klass, super_call, ctx);
+}
+
+static VALUE
+rb_super_objc_send(int argc, VALUE *argv, VALUE rcv)
+{
+    struct objc_ruby_closure_context fake_ctx;
+    id ocrcv;
+    ID mid;
+    Class klass;
+
+    if (argc < 1)
+	rb_raise(rb_eArgError, "expected at least one argument");
+
+    mid = rb_to_id(argv[0]);
+    argv++;
+    argc--;
+
+    rb_objc_rval_to_ocid(rcv, (void **)&ocrcv, true);
+    klass = class_getSuperclass(*(Class *)ocrcv);
+
+    fake_ctx.selector = sel_registerName(rb_id2name(mid));
+    fake_ctx.method = class_getInstanceMethod(klass, fake_ctx.selector); 
+    assert(fake_ctx.method != NULL);
+    fake_ctx.bs_method = NULL;
+    fake_ctx.cif = NULL;
+    fake_ctx.imp = NULL;
+    fake_ctx.klass = NULL;
+
+    return rb_objc_call_objc(argc, argv, ocrcv, klass, true, &fake_ctx);
+}
+
 #define IGNORE_PRIVATE_OBJC_METHODS 1
 
 static void
@@ -2521,6 +2577,13 @@
     return rb_objc_allocate(rcv);
 }
 
+static void *
+imp_rb_obj_init(void *rcv, SEL sel)
+{
+    rb_funcall((VALUE)rcv, idInitialize, 0);
+    return rcv;
+}
+
 static void
 rb_install_alloc_methods(void)
 {
@@ -2529,6 +2592,8 @@
     rb_objc_install_method(klass, @selector(alloc), (IMP)imp_rb_obj_alloc);
     rb_objc_install_method(klass, @selector(allocWithZone:), 
 	(IMP)imp_rb_obj_allocWithZone);
+    rb_objc_install_method(RCLASS_OCID(rb_cObject), @selector(init), 
+	(IMP)imp_rb_obj_init);
 }
 
 ID
@@ -2987,6 +3052,8 @@
 		CFAbsoluteTimeGetCurrent(), 0.1, 0, 0, timer_cb, NULL);
 	CFRunLoopAddTimer(CFRunLoopGetMain(), timer, kCFRunLoopDefaultMode);
     }
+
+    rb_define_method(rb_cBasicObject, "__super_objc_send__", rb_super_objc_send, -1);
 }
 
 @interface Protocol

Copied: MacRuby/branches/testing/sample-macruby/RubyCocoa (from rev 311, MacRuby/trunk/sample-macruby/RubyCocoa)

Deleted: MacRuby/branches/testing/sample-macruby/RubyCocoa/HelloWorld.rb
===================================================================
--- MacRuby/trunk/sample-macruby/RubyCocoa/HelloWorld.rb	2008-07-06 22:09:00 UTC (rev 311)
+++ MacRuby/branches/testing/sample-macruby/RubyCocoa/HelloWorld.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -1,70 +0,0 @@
-# HelloWorld.rb
-#
-# Translate HelloWorld.py of PyObjc (Python Objective-C Bridge) to
-# Ruby with RubyCocoa.
-#
-# A quick guide to runtime name mangling:
-#
-#    ObjC        becomes    Ruby
-#    [obj method]           obj.method
-#    [obj method: arg]      obj.method(arg)
-#    [obj method: arg1 withOtherArgs: arg2]
-#    obj.method_withOtherArgs(arg1, arg2)
-
-require 'osx/cocoa'
-include OSX
-
-class AppDelegate <  NSObject
-  def applicationDidFinishLaunching(aNotification)
-    puts "Hello, World!"
-  end
-  
-  def sayHello(sender)
-    puts "Hello again, World!"
-    speak "Hello again, World!"
-  end
-  
-  def speak(str)
-    script = NSAppleScript.alloc.initWithSource("say \"#{str}\"")
-    script.performSelector_withObject('executeAndReturnError:', nil)
-  end
-end
-
-if $0 == __FILE__ then
-  $stderr.print "just wait..." ; $stderr.flush
-  app = NSApplication.sharedApplication
-  
-  app.setDelegate AppDelegate.alloc.init
-  
-  frame = NSRect.new(NSSize.new(200.0, 300.0), NSSize.new(250.0, 100.0))
-  win = NSWindow.alloc.initWithContentRect_styleMask_backing_defer(frame, 15, 2, 0)
-  win.setTitle 'HelloWorld'
-  # floating window
-  win.setLevel 3
-  
-  hel = NSButton.alloc.initWithFrame(NSRect.new(NSSize.new(10.0, 10.0), NSSize.new(80.0, 80.0)))
-  win.contentView.addSubview(hel)
-  hel.setBezelStyle(4)
-  hel.setTitle( 'Hello!' )
-  hel.setTarget( app.delegate )
-  hel.setAction( "sayHello:" )
-  
-  beep = NSSound.alloc.initWithContentsOfFile_byReference( '/System/Library/Sounds/Tink.Aiff', 1 )
-  hel.setSound( beep )
-  
-  bye = NSButton.alloc.initWithFrame(NSRect.new(NSSize.new(100.0, 10.0), NSSize.new(80.0, 80.0)))
-  win.contentView.addSubview bye
-  bye.setBezelStyle 4
-  bye.setTarget app
-  bye.setAction 'stop:'
-  bye.setEnabled true
-  bye.setTitle 'Goodbye!'
-  
-  adios = NSSound.alloc.initWithContentsOfFile_byReference('/System/Library/Sounds/Basso.aiff', true)
-  bye.setSound( adios )
-  
-  win.display
-  win.orderFrontRegardless
-  
-  app.run
-end

Copied: MacRuby/branches/testing/sample-macruby/RubyCocoa/HelloWorld.rb (from rev 311, MacRuby/trunk/sample-macruby/RubyCocoa/HelloWorld.rb)
===================================================================
--- MacRuby/branches/testing/sample-macruby/RubyCocoa/HelloWorld.rb	                        (rev 0)
+++ MacRuby/branches/testing/sample-macruby/RubyCocoa/HelloWorld.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -0,0 +1,70 @@
+# HelloWorld.rb
+#
+# Translate HelloWorld.py of PyObjc (Python Objective-C Bridge) to
+# Ruby with RubyCocoa.
+#
+# A quick guide to runtime name mangling:
+#
+#    ObjC        becomes    Ruby
+#    [obj method]           obj.method
+#    [obj method: arg]      obj.method(arg)
+#    [obj method: arg1 withOtherArgs: arg2]
+#    obj.method_withOtherArgs(arg1, arg2)
+
+require 'osx/cocoa'
+include OSX
+
+class AppDelegate <  NSObject
+  def applicationDidFinishLaunching(aNotification)
+    puts "Hello, World!"
+  end
+  
+  def sayHello(sender)
+    puts "Hello again, World!"
+    speak "Hello again, World!"
+  end
+  
+  def speak(str)
+    script = NSAppleScript.alloc.initWithSource("say \"#{str}\"")
+    script.performSelector_withObject('executeAndReturnError:', nil)
+  end
+end
+
+if $0 == __FILE__ then
+  $stderr.print "just wait..." ; $stderr.flush
+  app = NSApplication.sharedApplication
+  
+  app.setDelegate AppDelegate.alloc.init
+  
+  frame = NSRect.new(NSSize.new(200.0, 300.0), NSSize.new(250.0, 100.0))
+  win = NSWindow.alloc.initWithContentRect_styleMask_backing_defer(frame, 15, 2, 0)
+  win.setTitle 'HelloWorld'
+  # floating window
+  win.setLevel 3
+  
+  hel = NSButton.alloc.initWithFrame(NSRect.new(NSSize.new(10.0, 10.0), NSSize.new(80.0, 80.0)))
+  win.contentView.addSubview(hel)
+  hel.setBezelStyle(4)
+  hel.setTitle( 'Hello!' )
+  hel.setTarget( app.delegate )
+  hel.setAction( "sayHello:" )
+  
+  beep = NSSound.alloc.initWithContentsOfFile_byReference( '/System/Library/Sounds/Tink.Aiff', 1 )
+  hel.setSound( beep )
+  
+  bye = NSButton.alloc.initWithFrame(NSRect.new(NSSize.new(100.0, 10.0), NSSize.new(80.0, 80.0)))
+  win.contentView.addSubview bye
+  bye.setBezelStyle 4
+  bye.setTarget app
+  bye.setAction 'stop:'
+  bye.setEnabled true
+  bye.setTitle 'Goodbye!'
+  
+  adios = NSSound.alloc.initWithContentsOfFile_byReference('/System/Library/Sounds/Basso.aiff', true)
+  bye.setSound( adios )
+  
+  win.display
+  win.orderFrontRegardless
+  
+  app.run
+end

Deleted: MacRuby/branches/testing/sample-macruby/RubyCocoa/README
===================================================================
--- MacRuby/trunk/sample-macruby/RubyCocoa/README	2008-07-06 22:09:00 UTC (rev 311)
+++ MacRuby/branches/testing/sample-macruby/RubyCocoa/README	2008-07-06 22:18:19 UTC (rev 312)
@@ -1,5 +0,0 @@
-sndplay.rb - Works.
-HelloWorld.rb - Sometimes hangs when pushing the hello button.
-fontnames.rb  - Works.
-darkroom.rb - Works (when used with these options: --output=google.png --height=600 http://google.com, there's a bug in darkroom which triggers when a height isn't specified). But needed to move #initialize code into #init because #initialize isn't called when used with alloc.init. However #init can't be used either in a real RubyCocoa way, because that would mean calling super_init which also isn't implemented yet.
-TransparentHello.rb - Works, but trying to interrupt the runloop doesn't work.
\ No newline at end of file

Copied: MacRuby/branches/testing/sample-macruby/RubyCocoa/README (from rev 311, MacRuby/trunk/sample-macruby/RubyCocoa/README)
===================================================================
--- MacRuby/branches/testing/sample-macruby/RubyCocoa/README	                        (rev 0)
+++ MacRuby/branches/testing/sample-macruby/RubyCocoa/README	2008-07-06 22:18:19 UTC (rev 312)
@@ -0,0 +1,5 @@
+sndplay.rb - Works.
+HelloWorld.rb - Sometimes hangs when pushing the hello button.
+fontnames.rb  - Works.
+darkroom.rb - Works (when used with these options: --output=google.png --height=600 http://google.com, there's a bug in darkroom which triggers when a height isn't specified). But needed to move #initialize code into #init because #initialize isn't called when used with alloc.init. However #init can't be used either in a real RubyCocoa way, because that would mean calling super_init which also isn't implemented yet.
+TransparentHello.rb - Works, but trying to interrupt the runloop doesn't work.
\ No newline at end of file

Deleted: MacRuby/branches/testing/sample-macruby/RubyCocoa/TransparentHello.rb
===================================================================
--- MacRuby/trunk/sample-macruby/RubyCocoa/TransparentHello.rb	2008-07-06 22:09:00 UTC (rev 311)
+++ MacRuby/branches/testing/sample-macruby/RubyCocoa/TransparentHello.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -1,88 +0,0 @@
-#
-# written by Chris Thomas for the article of DDJ May 2002.
-#
-
-require 'osx/cocoa'
-
-class HelloView < OSX::NSView
-  #
-  # When the Cocoa view system wants to draw a view,
-  # it calls the method -(void)drawRect:(NSRect)rect.
-  # The rectangle argument is relative to the origin
-  # of the view's frame, and it may only be a small
-  # portion of the view. For this reason, very
-  # simple views with only one or two graphical
-  # elements tend to ignore this parameter.
-  #
-  def drawRect(rect)
-    
-    # Set the window background to transparent
-    OSX::NSColor.clearColor.set
-    OSX::NSRectFill(bounds)
-    
-    # Draw the text in a shade of red and in a large system font
-    attributes = OSX::NSMutableDictionary.alloc.init
-    
-    attributes.setObject_forKey(OSX::NSColor.redColor, OSX::NSForegroundColorAttributeName)
-    attributes.setObject_forKey(OSX::NSFont.boldSystemFontOfSize(48.0), OSX::NSFontAttributeName)
-    
-    string = OSX::NSString.alloc.initWithString( "Hello, Ruby Baby" )
-    string.drawAtPoint_withAttributes(OSX::NSSize.new(0,0), attributes)
-    
-    #
-    # Turn the window's shadow off and on --
-    # This is a kludge to get the shadow to recalculate
-    # for the new shape of the opaque window content.
-    #
-    viewWindow = window
-    window.setHasShadow(0)
-    window.setHasShadow(1)
-  end
-end
-
-#
-# If this file is the main file, then perform the followjng commands.
-# (This construct is often useful for adding simple unit tests to
-# library code.)
-#
-if __FILE__ == $0
-  #
-  # First, to establish a connection to the window server,
-  # we must initialize the application
-  #
-  $stderr.print "just wait ..." ; $stderr.flush
-  application = OSX::NSApplication.sharedApplication
-  
-  # Create the window
-  window = OSX::NSWindow.alloc.
-    objc_send(:initWithContentRect, OSX::NSRect.new(OSX::NSSize.new(0, 0), OSX::NSSize.new(450, 200)),
-                        :styleMask, OSX::NSBorderlessWindowMask,
-                          :backing, OSX::NSBackingStoreBuffered,
-                            :defer, 0)
-  # Allow the window to be partially transparent
-  window.setOpaque(0)
-  
-  # Setup the window's root view
-  view = HelloView.alloc.initWithFrame(OSX::NSRect.new(OSX::NSSize.new(0, 0), OSX::NSSize.new(450, 200)))
-  window.setContentView(view)
-  
-  # Place the window near the top of the screen.
-  # (Screen coordinates in Cocoa are always PostScript
-  # coordinates, which start from the bottom of the screen
-  # and increase as they go up, so we have to do some math
-  # to place the window at 100 pixels from the top of the
-  # screen.
-  #
-  screenFrame = OSX::NSScreen.mainScreen.frame
-  windowOriginPoint = OSX::NSSize.new(40, screenFrame.origin.y + screenFrame.size.height - 100)
-  window.setFrameOrigin( windowOriginPoint )
-  
-  # Show the window
-  window.makeKeyAndOrderFront(nil)
-  window.orderFrontRegardless()    ## but this one does
-  
-  # And start the application event loop
-  $stderr.print "\rtype `Ctrl-C' for quit !\n"
-  trap('SIGINT') { $stderr.puts "bye." ; exit 0 }
-  application.run
-end

Copied: MacRuby/branches/testing/sample-macruby/RubyCocoa/TransparentHello.rb (from rev 311, MacRuby/trunk/sample-macruby/RubyCocoa/TransparentHello.rb)
===================================================================
--- MacRuby/branches/testing/sample-macruby/RubyCocoa/TransparentHello.rb	                        (rev 0)
+++ MacRuby/branches/testing/sample-macruby/RubyCocoa/TransparentHello.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -0,0 +1,88 @@
+#
+# written by Chris Thomas for the article of DDJ May 2002.
+#
+
+require 'osx/cocoa'
+
+class HelloView < OSX::NSView
+  #
+  # When the Cocoa view system wants to draw a view,
+  # it calls the method -(void)drawRect:(NSRect)rect.
+  # The rectangle argument is relative to the origin
+  # of the view's frame, and it may only be a small
+  # portion of the view. For this reason, very
+  # simple views with only one or two graphical
+  # elements tend to ignore this parameter.
+  #
+  def drawRect(rect)
+    
+    # Set the window background to transparent
+    OSX::NSColor.clearColor.set
+    OSX::NSRectFill(bounds)
+    
+    # Draw the text in a shade of red and in a large system font
+    attributes = OSX::NSMutableDictionary.alloc.init
+    
+    attributes.setObject_forKey(OSX::NSColor.redColor, OSX::NSForegroundColorAttributeName)
+    attributes.setObject_forKey(OSX::NSFont.boldSystemFontOfSize(48.0), OSX::NSFontAttributeName)
+    
+    string = OSX::NSString.alloc.initWithString( "Hello, Ruby Baby" )
+    string.drawAtPoint_withAttributes(OSX::NSSize.new(0,0), attributes)
+    
+    #
+    # Turn the window's shadow off and on --
+    # This is a kludge to get the shadow to recalculate
+    # for the new shape of the opaque window content.
+    #
+    viewWindow = window
+    window.setHasShadow(0)
+    window.setHasShadow(1)
+  end
+end
+
+#
+# If this file is the main file, then perform the followjng commands.
+# (This construct is often useful for adding simple unit tests to
+# library code.)
+#
+if __FILE__ == $0
+  #
+  # First, to establish a connection to the window server,
+  # we must initialize the application
+  #
+  $stderr.print "just wait ..." ; $stderr.flush
+  application = OSX::NSApplication.sharedApplication
+  
+  # Create the window
+  window = OSX::NSWindow.alloc.
+    objc_send(:initWithContentRect, OSX::NSRect.new(OSX::NSSize.new(0, 0), OSX::NSSize.new(450, 200)),
+                        :styleMask, OSX::NSBorderlessWindowMask,
+                          :backing, OSX::NSBackingStoreBuffered,
+                            :defer, 0)
+  # Allow the window to be partially transparent
+  window.setOpaque(0)
+  
+  # Setup the window's root view
+  view = HelloView.alloc.initWithFrame(OSX::NSRect.new(OSX::NSSize.new(0, 0), OSX::NSSize.new(450, 200)))
+  window.setContentView(view)
+  
+  # Place the window near the top of the screen.
+  # (Screen coordinates in Cocoa are always PostScript
+  # coordinates, which start from the bottom of the screen
+  # and increase as they go up, so we have to do some math
+  # to place the window at 100 pixels from the top of the
+  # screen.
+  #
+  screenFrame = OSX::NSScreen.mainScreen.frame
+  windowOriginPoint = OSX::NSSize.new(40, screenFrame.origin.y + screenFrame.size.height - 100)
+  window.setFrameOrigin( windowOriginPoint )
+  
+  # Show the window
+  window.makeKeyAndOrderFront(nil)
+  window.orderFrontRegardless()    ## but this one does
+  
+  # And start the application event loop
+  $stderr.print "\rtype `Ctrl-C' for quit !\n"
+  trap('SIGINT') { $stderr.puts "bye." ; exit 0 }
+  application.run
+end

Deleted: MacRuby/branches/testing/sample-macruby/RubyCocoa/darkroom.rb
===================================================================
--- MacRuby/trunk/sample-macruby/RubyCocoa/darkroom.rb	2008-07-06 22:09:00 UTC (rev 311)
+++ MacRuby/branches/testing/sample-macruby/RubyCocoa/darkroom.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -1,128 +0,0 @@
-#!/usr/bin/env ruby
-#
-# DarkRoom
-# Takes fullsize screenshots of a web page.
-# Copyright (c) 2007 Justin Palmer.
-#
-# Released under an MIT LICENSE
-#
-# Usage
-# ====
-# ruby ./darkroom.rb http://activereload.net
-# ruby ./darkroom.rb --output=google.png http://google.com
-# ruby ./darkroom.rb --width=400 --delay=5 http://yahoo.com
-#
-# As a fix for the current bug specify a height:
-# macruby darkroom.rb --output=google.png --height=600 http://google.com
-require 'optparse'
-require 'osx/cocoa'
-OSX.require_framework 'Webkit'
-
-module ActiveReload
-  module DarkRoom
-    USER_AGENT = "DarkRoom/0.1"
-    class Photographer
-      def initialize
-        options = {}
-        opts = OptionParser.new do |opts|
-          opts.banner = "Usage: #$0 [options] URL"
-          
-          opts.on('-w', '--width=[WIDTH]', Integer, 'Force width of the screenshot') do |v|
-            options[:width] = v
-          end
-          
-          opts.on('-h', '--height=[HEIGHT]', Integer, 'Force height of screenshot') do |v|
-            options[:height] = v
-          end
-          
-          opts.on('-o', '--output=[FILENAME]', String, 'Specify filename for saving') do |v|
-            options[:output] = v
-          end
-          
-          opts.on('-d', '--delay=[DELAY]', Integer, 'Delay in seconds to give web page assets time to load') do |v|
-            options[:delay] = v
-          end
-          
-          opts.on_tail('-h', '--help', 'Display this message and exit') do
-            puts opts
-            exit
-          end
-        end.parse!
-        options[:width]  ||= 1024
-        options[:height] ||= 0
-        options[:website] = ARGV.first || 'http://google.com'
-        Camera.shoot(options)
-      end
-    end
-    
-    class Camera
-      def self.shoot(options)
-        app = OSX::NSApplication.sharedApplication
-        delegate = Processor.alloc.init!
-        delegate.options = options
-        app.setDelegate(delegate)
-        app.run
-      end
-    end
-    
-    class Processor < OSX::NSObject
-      include OSX
-      attr_accessor :options, :web_view
-      
-      # def initialize
-      #   #puts 'inits'
-      #   rect = [-16000.0, -16000.0, 100, 100]
-      #   win = NSWindow.alloc.initWithContentRect_styleMask_backing_defer(rect, NSBorderlessWindowMask, 2, 0)
-      #   
-      #   @web_view = WebView.alloc.initWithFrame(rect)
-      #   @web_view.mainFrame.frameView.setAllowsScrolling(false)
-      #   @web_view.setApplicationNameForUserAgent(USER_AGENT)
-      #   @web_view.setFrameLoadDelegate(self)
-      #   
-      #   win.setContentView(@web_view)
-      # end
-      
-      def init!
-        if init
-          rect = NSRect.new(NSSize.new(-16000.0, -16000.0), NSSize.new(100, 100))
-          win = NSWindow.alloc.initWithContentRect_styleMask_backing_defer(rect, OSX::NSBorderlessWindowMask, 2, 0)
-          
-          @web_view = WebView.alloc.initWithFrame(rect)
-          @web_view.mainFrame.frameView.setAllowsScrolling(false)
-          @web_view.setApplicationNameForUserAgent(USER_AGENT)
-          @web_view.setFrameLoadDelegate(self)
-          win.setContentView(@web_view)
-          
-          self
-        end
-      end
-      
-      def applicationDidFinishLaunching(notification)
-        @options[:output] ||= "#{Time.now.strftime('%m-%d-%y-%H%I%S')}.png"
-        @web_view.window.setContentSize(NSSize.new(@options[:width], @options[:height]))
-        @web_view.setFrameSize(NSSize.new(@options[:width], @options[:height]))
-        @web_view.mainFrame.loadRequest(NSURLRequest.requestWithURL(NSURL.URLWithString(@options[:website])))
-      end
-      
-      def webView_didFinishLoadForFrame(web_view, frame)
-        viewport = web_view.mainFrame.frameView.documentView
-        viewport.window.orderFront(nil)
-        viewport.window.display
-        viewport.window.setContentSize(NSSize.new(@options[:width], (@options[:height] > 0 ? @options[:height] : viewport.bounds.height)))
-        viewport.setFrame(viewport.bounds)
-        sleep(@options[:delay]) if @options[:delay]
-        capture_and_save(viewport)
-      end
-      
-      def capture_and_save(view)
-        view.lockFocus
-          bitmap = NSBitmapImageRep.alloc.initWithFocusedViewRect(view.bounds)
-        view.unlockFocus
-        
-        bitmap.representationUsingType_properties(OSX::NSPNGFileType, nil).writeToFile_atomically(@options[:output], true)
-        NSApplication.sharedApplication.terminate(nil)
-      end
-    end
-  end
-end
-ActiveReload::DarkRoom::Photographer.new

Copied: MacRuby/branches/testing/sample-macruby/RubyCocoa/darkroom.rb (from rev 311, MacRuby/trunk/sample-macruby/RubyCocoa/darkroom.rb)
===================================================================
--- MacRuby/branches/testing/sample-macruby/RubyCocoa/darkroom.rb	                        (rev 0)
+++ MacRuby/branches/testing/sample-macruby/RubyCocoa/darkroom.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -0,0 +1,128 @@
+#!/usr/bin/env ruby
+#
+# DarkRoom
+# Takes fullsize screenshots of a web page.
+# Copyright (c) 2007 Justin Palmer.
+#
+# Released under an MIT LICENSE
+#
+# Usage
+# ====
+# ruby ./darkroom.rb http://activereload.net
+# ruby ./darkroom.rb --output=google.png http://google.com
+# ruby ./darkroom.rb --width=400 --delay=5 http://yahoo.com
+#
+# As a fix for the current bug specify a height:
+# macruby darkroom.rb --output=google.png --height=600 http://google.com
+require 'optparse'
+require 'osx/cocoa'
+OSX.require_framework 'Webkit'
+
+module ActiveReload
+  module DarkRoom
+    USER_AGENT = "DarkRoom/0.1"
+    class Photographer
+      def initialize
+        options = {}
+        opts = OptionParser.new do |opts|
+          opts.banner = "Usage: #$0 [options] URL"
+          
+          opts.on('-w', '--width=[WIDTH]', Integer, 'Force width of the screenshot') do |v|
+            options[:width] = v
+          end
+          
+          opts.on('-h', '--height=[HEIGHT]', Integer, 'Force height of screenshot') do |v|
+            options[:height] = v
+          end
+          
+          opts.on('-o', '--output=[FILENAME]', String, 'Specify filename for saving') do |v|
+            options[:output] = v
+          end
+          
+          opts.on('-d', '--delay=[DELAY]', Integer, 'Delay in seconds to give web page assets time to load') do |v|
+            options[:delay] = v
+          end
+          
+          opts.on_tail('-h', '--help', 'Display this message and exit') do
+            puts opts
+            exit
+          end
+        end.parse!
+        options[:width]  ||= 1024
+        options[:height] ||= 0
+        options[:website] = ARGV.first || 'http://google.com'
+        Camera.shoot(options)
+      end
+    end
+    
+    class Camera
+      def self.shoot(options)
+        app = OSX::NSApplication.sharedApplication
+        delegate = Processor.alloc.init!
+        delegate.options = options
+        app.setDelegate(delegate)
+        app.run
+      end
+    end
+    
+    class Processor < OSX::NSObject
+      include OSX
+      attr_accessor :options, :web_view
+      
+      # def initialize
+      #   #puts 'inits'
+      #   rect = [-16000.0, -16000.0, 100, 100]
+      #   win = NSWindow.alloc.initWithContentRect_styleMask_backing_defer(rect, NSBorderlessWindowMask, 2, 0)
+      #   
+      #   @web_view = WebView.alloc.initWithFrame(rect)
+      #   @web_view.mainFrame.frameView.setAllowsScrolling(false)
+      #   @web_view.setApplicationNameForUserAgent(USER_AGENT)
+      #   @web_view.setFrameLoadDelegate(self)
+      #   
+      #   win.setContentView(@web_view)
+      # end
+      
+      def init!
+        if init
+          rect = NSRect.new(NSSize.new(-16000.0, -16000.0), NSSize.new(100, 100))
+          win = NSWindow.alloc.initWithContentRect_styleMask_backing_defer(rect, OSX::NSBorderlessWindowMask, 2, 0)
+          
+          @web_view = WebView.alloc.initWithFrame(rect)
+          @web_view.mainFrame.frameView.setAllowsScrolling(false)
+          @web_view.setApplicationNameForUserAgent(USER_AGENT)
+          @web_view.setFrameLoadDelegate(self)
+          win.setContentView(@web_view)
+          
+          self
+        end
+      end
+      
+      def applicationDidFinishLaunching(notification)
+        @options[:output] ||= "#{Time.now.strftime('%m-%d-%y-%H%I%S')}.png"
+        @web_view.window.setContentSize(NSSize.new(@options[:width], @options[:height]))
+        @web_view.setFrameSize(NSSize.new(@options[:width], @options[:height]))
+        @web_view.mainFrame.loadRequest(NSURLRequest.requestWithURL(NSURL.URLWithString(@options[:website])))
+      end
+      
+      def webView_didFinishLoadForFrame(web_view, frame)
+        viewport = web_view.mainFrame.frameView.documentView
+        viewport.window.orderFront(nil)
+        viewport.window.display
+        viewport.window.setContentSize(NSSize.new(@options[:width], (@options[:height] > 0 ? @options[:height] : viewport.bounds.height)))
+        viewport.setFrame(viewport.bounds)
+        sleep(@options[:delay]) if @options[:delay]
+        capture_and_save(viewport)
+      end
+      
+      def capture_and_save(view)
+        view.lockFocus
+          bitmap = NSBitmapImageRep.alloc.initWithFocusedViewRect(view.bounds)
+        view.unlockFocus
+        
+        bitmap.representationUsingType_properties(OSX::NSPNGFileType, nil).writeToFile_atomically(@options[:output], true)
+        NSApplication.sharedApplication.terminate(nil)
+      end
+    end
+  end
+end
+ActiveReload::DarkRoom::Photographer.new

Deleted: MacRuby/branches/testing/sample-macruby/RubyCocoa/fontnames.rb
===================================================================
--- MacRuby/trunk/sample-macruby/RubyCocoa/fontnames.rb	2008-07-06 22:09:00 UTC (rev 311)
+++ MacRuby/branches/testing/sample-macruby/RubyCocoa/fontnames.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -1,11 +0,0 @@
-require 'osx/cocoa'
-
-fmgr = OSX::NSFontManager.sharedFontManager
-
-puts "## all fonts ##"
-fonts = fmgr.availableFonts.to_a.map{|i| i.to_s }
-fonts.each {|i| puts i }
-
-puts "## fixed pitch fonts ##"
-fixedfonts = fmgr.availableFontNamesWithTraits(OSX::NSFixedPitchFontMask).to_a
-fixedfonts.each {|i| puts i.to_s }
\ No newline at end of file

Copied: MacRuby/branches/testing/sample-macruby/RubyCocoa/fontnames.rb (from rev 311, MacRuby/trunk/sample-macruby/RubyCocoa/fontnames.rb)
===================================================================
--- MacRuby/branches/testing/sample-macruby/RubyCocoa/fontnames.rb	                        (rev 0)
+++ MacRuby/branches/testing/sample-macruby/RubyCocoa/fontnames.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -0,0 +1,11 @@
+require 'osx/cocoa'
+
+fmgr = OSX::NSFontManager.sharedFontManager
+
+puts "## all fonts ##"
+fonts = fmgr.availableFonts.to_a.map{|i| i.to_s }
+fonts.each {|i| puts i }
+
+puts "## fixed pitch fonts ##"
+fixedfonts = fmgr.availableFontNamesWithTraits(OSX::NSFixedPitchFontMask).to_a
+fixedfonts.each {|i| puts i.to_s }
\ No newline at end of file

Deleted: MacRuby/branches/testing/sample-macruby/RubyCocoa/sndplay.rb
===================================================================
--- MacRuby/trunk/sample-macruby/RubyCocoa/sndplay.rb	2008-07-06 22:09:00 UTC (rev 311)
+++ MacRuby/branches/testing/sample-macruby/RubyCocoa/sndplay.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -1,14 +0,0 @@
-require 'osx/cocoa'
-
-snd_files =
-  if ARGV.size == 0 then
-    `ls /System/Library/Sounds/*.aiff`.split
-  else
-    ARGV
-  end
-
-snd_files.each do |path|
-  snd = OSX::NSSound.alloc.initWithContentsOfFile_byReference(path, true)
-  snd.play
-  sleep 0.25 while snd.playing?
-end
\ No newline at end of file

Copied: MacRuby/branches/testing/sample-macruby/RubyCocoa/sndplay.rb (from rev 311, MacRuby/trunk/sample-macruby/RubyCocoa/sndplay.rb)
===================================================================
--- MacRuby/branches/testing/sample-macruby/RubyCocoa/sndplay.rb	                        (rev 0)
+++ MacRuby/branches/testing/sample-macruby/RubyCocoa/sndplay.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -0,0 +1,14 @@
+require 'osx/cocoa'
+
+snd_files =
+  if ARGV.size == 0 then
+    `ls /System/Library/Sounds/*.aiff`.split
+  else
+    ARGV
+  end
+
+snd_files.each do |path|
+  snd = OSX::NSSound.alloc.initWithContentsOfFile_byReference(path, true)
+  snd.play
+  sleep 0.25 while snd.playing?
+end
\ No newline at end of file

Modified: MacRuby/branches/testing/test/ruby/test_objc.rb
===================================================================
--- MacRuby/branches/testing/test/ruby/test_objc.rb	2008-07-06 22:09:00 UTC (rev 311)
+++ MacRuby/branches/testing/test/ruby/test_objc.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -71,6 +71,26 @@
     assert_equal('xxxyyy', r)
   end
 
+  class TestSuperMethod
+    def init
+      super
+      @foo = 42
+      self
+    end
+    attr_reader :foo
+  end
+  def test_super_method
+    obj = TestSuperMethod.alloc.init
+    assert_equal(42, obj.foo)
+    obj = TestSuperMethod.performSelector(:alloc).performSelector(:init)
+    assert_equal(42, obj.foo)
+    # FIXME this doesn't work yet
+    #obj = TestSuperMethod.new
+    #assert_equal(42, obj.foo)
+    obj = TestSuperMethod.performSelector(:new)
+    assert_equal(42, obj.foo)
+  end
+
   def test_pure_objc_ivar
     o = NSObject.alloc.init
     assert_kind_of(NSObject, o)
@@ -147,5 +167,64 @@
     assert_raise(ArgumentError) { NSStringFromRect([1, 2, 3, 4, 5]) }
   end
 
+  class TestInitCallInitialize
+    attr_reader :foo
+    def initialize
+      @foo = 42
+    end
+  end
+  def test_init_call_initialize
+    o = TestInitCallInitialize.new
+    assert_equal(42, o.foo)
+    o = TestInitCallInitialize.alloc.init
+    assert_equal(42, o.foo)
+  end
+
+  def test_call_self
+    o = Object.new
+    assert_equal(o, o.self)
+    s = 'foo'
+    assert_equal(s, s.self)
+    n = 42
+    assert_kind_of(NSNumber, n.self)
+    assert_equal(42, n.self.intValue)
+    n = nil
+    assert_kind_of(NSNull, n.self)
+    assert_equal(NSNull.null, n.self)
+    # TODO this currently SEGV
+    #m = String
+    #assert_equal(m, m.self)
+  end
+
+  def test_call_superclass
+    o = Object.new
+    assert_equal(NSObject, o.superclass)
+    s = 'foo'
+    assert_equal(NSMutableString, s.superclass)
+    n = 42
+    assert_equal(NSNumber, n.superclass)
+    n = nil 
+    assert_equal(NSObject, n.superclass)
+  end
+
+  def test_no_direct_nsobject_subclass
+    old_verbose = $VERBOSE
+    $VERBOSE = nil # no warn
+    klass = eval("class Foo < NSObject; end; Foo")
+    assert_equal(Object, klass.superclass)
+    $VERBOSE = old_verbose
+  end
+
+  class TestSuper1
+    def foo; 'xxx'; end
+  end
+  class TestSuper2 < TestSuper1
+    def bar; __super_objc_send__(:foo); end
+  end
+  def test_objc_super
+    o = TestSuper2.new
+    assert_equal('xxx', o.bar)
+  end
+
 end
 

Copied: MacRuby/branches/testing/test-macruby/rubycocoa_test.rb (from rev 311, MacRuby/trunk/test-macruby/rubycocoa_test.rb)
===================================================================
--- MacRuby/branches/testing/test-macruby/rubycocoa_test.rb	                        (rev 0)
+++ MacRuby/branches/testing/test-macruby/rubycocoa_test.rb	2008-07-06 22:18:19 UTC (rev 312)
@@ -0,0 +1,179 @@
+#!/usr/local/bin/macruby
+
+require "test/spec"
+require 'mocha'
+
+#require File.expand_path('../../lib/osx/cocoa', __FILE__)
+require 'osx/cocoa'
+
+class TestRubyCocoaStyleMethod < OSX::NSObject
+  def initialize
+    @set_from_initialize = 'represent!'
+  end
+  
+  def perform_selector_with_object(sel, obj)
+    callMethod_withArgs(sel, obj)
+  end
+  
+  def callMethod(method, withArgs:args)
+    send(method, *args)
+  end
+  
+  def method_rubyCocoaStyle_withExtraArg(mname, rc_style, arg)
+    "#{mname}(#{rc_style}, #{arg})"
+  end
+  
+  def method_notRubyCocoaStyle(first_arg, second_arg, third_arg)
+  end
+  
+  def self.classMethod(mname, macRubyStyle:mr_style, withExtraArg:arg)
+    "#{mname}(#{mr_style}, #{arg})"
+  end
+end
+
+class TestRubyCocoaStyleSuperMethod < OSX::NSObject
+  def init
+    self if super_init
+  end
+end
+
+class NSObjectSubclassWithInitialize < OSX::NSObject
+  def initialize
+    @set_from_initialize = 'represent!'
+  end
+end
+
+class NSObjectSubclassWithoutInitialize < OSX::NSObject; end
+
+CONSTANT_IN_THE_TOPLEVEL_OBJECT_INSTEAD_OF_OSX = true
+
+describe "RubyCocoa layer, in general" do
+  xit "should load AppKit when the osx/cocoa file is loaded" do
+    Kernel.expects(:framework).with('AppKit')
+    load 'osx/cocoa.rb'
+  end
+  
+  it "should set a global variable which indicates that a framework is being loaded" do
+    Kernel.expects(:__framework_before_rubycocoa_layer).with do |f|
+      $LOADING_FRAMEWORK.should.be true
+      f == 'Foo'
+    end
+    Kernel.framework 'Foo'
+    $LOADING_FRAMEWORK.should.be false
+  end
+end
+
+describe "NSObject additions" do
+  before do
+    @obj = TestRubyCocoaStyleMethod.alloc.init
+  end
+  
+  it "should alias ib_outlet to ib_outlets" do
+    TestRubyCocoaStyleMethod.private_methods.should.include :ib_outlets
+  end
+  
+  it "should call initialize from init if it exists" do
+    NSObjectSubclassWithInitialize.alloc.init.instance_variable_get(:@set_from_initialize).should == 'represent!'
+    NSObjectSubclassWithoutInitialize.alloc.init.instance_variable_get(:@set_from_initialize).should.be nil
+  end
+  
+  it "should catch RubyCocoa style instance method, call the correct MacRuby style method and define a shortcut method" do
+    @obj.perform_selector_with_object('description', nil).should.match /^<TestRubyCocoaStyleMethod/
+    @obj.respond_to?(:callMethod_withArgs).should.be true
+    @obj.perform_selector_with_object('description', nil).should.match /^<TestRubyCocoaStyleMethod/
+  end
+  
+  it "should catch RubyCocoa style instance methods that end with a underscore" do
+    @obj.callMethod_withArgs_('description', nil).should.match /^<TestRubyCocoaStyleMethod/
+    @obj.respond_to?(:callMethod_withArgs_).should.be true
+  end
+  
+  it "should catch RubyCocoa style instance methods defined in Objective-C" do
+    color = NSColor.colorWithCalibratedRed(1.0, green:1.0, blue:1.0, alpha:1.0)
+    lambda { color.blendedColorWithFraction_ofColor(0.5, NSColor.greenColor) }.should.not.raise NoMethodError
+  end
+  
+  it "should catch RubyCocoa style class methods defined in ruby" do
+    lambda { TestRubyCocoaStyleMethod.classMethod_macRubyStyle_withExtraArg(1, 2, 3) }.should.not.raise NoMethodError
+    TestRubyCocoaStyleMethod.respond_to?(:classMethod_macRubyStyle_withExtraArg).should.be true
+  end
+  
+  it "should catch RubyCocoa style class methods defined in Objective-C" do
+    lambda { NSColor.colorWithCalibratedRed_green_blue_alpha(1.0, 1.0, 1.0, 1.0) }.should.not.raise NoMethodError
+    NSColor.respond_to?(:colorWithCalibratedRed_green_blue_alpha).should.be true
+  end
+  
+  it "should still raise NoMethodError if a class method doesn't exist" do
+    lambda { NSColor.colorWithCalibratedRed_pink(1.0, 1.0) }.should.raise NoMethodError
+  end
+  
+  it "should also work on other regular NSObject subclasses" do
+    nsstring = 'foo'
+    nsstring.insertString_atIndex('bar', 3)
+    nsstring.should == 'foobar'
+  end
+  
+  it "should still raise a NoMethodError if the selector doesn't exist when a method is missing" do
+    lambda { @obj.does_not_exist }.should.raise NoMethodError
+    lambda { @obj.doesnotexist_ }.should.raise NoMethodError
+    lambda { @obj.doesnotexist }.should.raise NoMethodError
+  end
+  
+  it "should be possible to call super_foo type methods" do
+    lambda { TestRubyCocoaStyleSuperMethod.alloc.init }.should.not.raise.exception
+  end
+  
+  it "should handle objc_send style methods" do
+    nsstring = 'foo'
+    nsstring.objc_send(:insertString, 'bar', :atIndex, 3)
+    nsstring.should == 'foobar'
+    nsstring.objc_send(:description).should == 'foobar'
+    lambda { nsstring.objc_send(:does_not_exist) }.should.raise NoMethodError
+  end
+  
+  it "should create MacRuby style method aliases for any method containing underscores" do
+    @obj.respond_to?(:"method:rubyCocoaStyle:withExtraArg:").should.be true
+    @obj.method('foo', rubyCocoaStyle:true, withExtraArg:false).should == 'foo(true, false)'
+  end
+  
+  it "should not create MacRuby style method aliases for methods containing underscores if the arity doesn't match" do
+    @obj.respond_to?(:"method:notRubyCocoaStyle:").should.be false
+  end
+end
+
+describe 'OSX module' do
+  it "should exist" do
+    defined?(OSX).should.not.be nil # this is weird.. I haven't defined OSX yet?!
+  end
+  
+  it "should load a framework into the runtime" do
+    OSX.require_framework 'WebKit'
+    defined?(WebView).should.not.be nil
+    
+    OSX.require_framework '/System/Library/Frameworks/QTKit.framework'
+    defined?(QTMovie).should.not.be nil
+  end
+  
+  it "should forward messages to Kernel if it responds to it" do
+    Kernel.expects(:NSRectFill).with(1, 2).times(2)
+    OSX::NSRectFill(1, 2)
+    OSX.respond_to?(:NSRectFill).should.be true
+    OSX::NSRectFill(1, 2)
+    
+    lambda { OSX::NSRectFillllllll(1, 2) }.should.raise NoMethodError
+  end
+  
+  it "should try to get missing constants from the toplevel object" do
+    OSX::CONSTANT_IN_THE_TOPLEVEL_OBJECT_INSTEAD_OF_OSX.should.be true
+  end
+  
+  it "should still raise a NameError from OSX, not from the toplevel object, when a constant is missing" do
+    lambda { OSX::DOES_NOT_EXIST_IN_TOPLEVEL_OBJECT }.should.raise NameError
+    
+    begin
+      OSX::DOES_NOT_EXIST_IN_TOPLEVEL_OBJECT
+    rescue NameError => e
+      e.message.should.include 'OSX::DOES_NOT_EXIST_IN_TOPLEVEL_OBJECT'
+    end
+  end
+end
\ No newline at end of file

Modified: MacRuby/branches/testing/vm.c
===================================================================
--- MacRuby/branches/testing/vm.c	2008-07-06 22:09:00 UTC (rev 311)
+++ MacRuby/branches/testing/vm.c	2008-07-06 22:18:19 UTC (rev 312)
@@ -14,6 +14,10 @@
 #include "ruby/encoding.h"
 #include "gc.h"
 
+#if WITH_OBJC
+NODE *rb_current_cfunc_node = NULL;
+#endif
+
 #include "insnhelper.h"
 #include "vm_insnhelper.c"
 #include "vm_eval.c"

Modified: MacRuby/branches/testing/vm_eval.c
===================================================================
--- MacRuby/branches/testing/vm_eval.c	2008-07-06 22:09:00 UTC (rev 311)
+++ MacRuby/branches/testing/vm_eval.c	2008-07-06 22:18:19 UTC (rev 312)
@@ -72,7 +72,13 @@
 	    cfp->method_id = id;
 	    cfp->method_class = klass;
 
+#if WITH_OBJC
+	    rb_current_cfunc_node = (NODE *)body;
+#endif
 	    val = call_cfunc(body->nd_cfnc, recv, body->nd_argc, argc, argv);
+#if WITH_OBJC
+	    rb_current_cfunc_node = NULL;
+#endif
 
 	    if (reg_cfp != th->cfp + 1) {
 		SDR2(reg_cfp);

Modified: MacRuby/branches/testing/vm_insnhelper.c
===================================================================
--- MacRuby/branches/testing/vm_insnhelper.c	2008-07-06 22:09:00 UTC (rev 311)
+++ MacRuby/branches/testing/vm_insnhelper.c	2008-07-06 22:18:19 UTC (rev 312)
@@ -353,10 +353,6 @@
     return Qnil;		/* not reached */
 }
 
-#if WITH_OBJC
-NODE *rb_current_cfunc_node = NULL;
-#endif
-
 static inline VALUE
 vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp,
 	      int num, ID id, VALUE recv, VALUE klass,
@@ -1130,6 +1126,11 @@
     if (*pmn == NULL) {
 	const char *p, *mname;
 	long i;
+	mn = rb_objc_define_objc_mid_closure(recv, *pid, 0);
+	if (mn != NULL) {
+	    *pmn = mn;
+	    return;
+	}
 	mname = rb_id2name(*pid);
 	if (*pid > 1 && (p = strchr(mname, ':')) != NULL) {
 	    char buf[512];
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macruby-changes/attachments/20080706/83820254/attachment-0001.html 


More information about the macruby-changes mailing list