Subject: Added back in Ruby 1.8 support. Tested under 1.8.6 and 1.9.1.
 The 1.8/1.9 compile time switching is done using a few macros. I'm not
 sure if this is the best way to achieve this or not, since I'm not too
 familiar with the (Ruby)C way. Any comments on the style will be
 appreciated!
From: Mark Somerville <mark@scottishclimbs.com>
Origin: https://github.com/Spakman/ruby-gd/commit/30eb7696a4fad4fc18cf11725da95226e79afd8e
Last-Update: 2009-09-10

--- a/GD.c
+++ b/GD.c
@@ -10,7 +10,11 @@
   $Revision: 1.6.2.3 $
 **************************************************************/
 #include "ruby.h"
-#include "ruby/io.h"
+#if defined(HAVE_RUBY_IO_H)
+        #include "ruby/io.h"
+#else /* seems like Ruby < 1.9 */
+        #include "rubyio.h"
+#endif
 
 #include "gd.h"
 #include "gdfontg.h"		/* giant */
@@ -19,6 +23,22 @@
 #include "gdfonts.h"		/* small */
 #include "gdfontt.h"		/* tiny */
 
+/* Is this the best way to do this sort of thing?
+ * It feels kind of wrong, but I'm not sure of the (Ruby)C way.
+ * Any opinions on the style will be gratefully received! */
+
+#if defined(HAVE_RUBY_IO_H) /* seems like Ruby > 1.8 */
+        #define FPTR_TYPE rb_io_t
+        #define FILE_POINTER_FOR_CREATE_FROM fdopen(fptr->fd, "r")
+        #define FPTR_PATH (char*)fptr->pathv
+        #define SECOND_FILE_POINTER rb_io_stdio_file(fptr)
+#else
+        #define FPTR_TYPE OpenFile
+        #define FILE_POINTER_FOR_CREATE_FROM fptr->f
+        #define FPTR_PATH fptr->path
+        #define SECOND_FILE_POINTER (fptr->f2) ? fptr->f2 : fptr->f
+#endif
+
 extern VALUE rb_io_binmode(VALUE io);
 extern gdImagePtr gdImageCreateFromXpm(char* );
 
@@ -61,7 +81,7 @@
     VALUE klass, fname;
 {
     VALUE f;
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr iptr;
     
     Check_Type(fname, T_STRING);
@@ -71,9 +91,9 @@
     GetOpenFile(f, fptr);
     rb_io_check_readable(fptr);
 
-    iptr = gdImageCreateFromPng(fdopen(fptr->fd, "r"));
+    iptr = gdImageCreateFromPng(FILE_POINTER_FOR_CREATE_FROM);
     if (!iptr)
-        rb_raise(rb_eArgError, "%s is not a valid PNG File", (char*)fptr->pathv);
+        rb_raise(rb_eArgError, "%s is not a valid PNG File", FPTR_PATH);
                  
     return Data_Wrap_Struct(klass,0,free_img,iptr);
 }
@@ -83,7 +103,7 @@
 img_from_png(klass, f)
     VALUE klass, f;
 {
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr iptr;
 
     Check_Type(f, T_FILE); 
@@ -91,9 +111,9 @@
     GetOpenFile(f, fptr);
     rb_io_check_readable(fptr);
 
-    iptr = gdImageCreateFromPng(fdopen(fptr->fd, "r"));
+    iptr = gdImageCreateFromPng(FILE_POINTER_FOR_CREATE_FROM);
     if (!iptr)
-        rb_raise(rb_eArgError, "%s is not a valid PNG File", (char*)fptr->pathv);
+        rb_raise(rb_eArgError, "%s is not a valid PNG File", FPTR_PATH);
                  
     return Data_Wrap_Struct(klass,0,free_img,iptr);
 }
@@ -104,7 +124,7 @@
     VALUE klass, fname;
 {
     VALUE f;
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr iptr;
     
     Check_Type(fname, T_STRING);
@@ -114,9 +134,9 @@
     GetOpenFile(f, fptr);
     rb_io_check_readable(fptr);
 
-    iptr = gdImageCreateFromGif(fdopen(fptr->fd, "r"));
+    iptr = gdImageCreateFromGif(FILE_POINTER_FOR_CREATE_FROM);
     if (!iptr)
-        rb_raise(rb_eArgError, "%s is not a valid GIF File", (char*)fptr->pathv);
+        rb_raise(rb_eArgError, "%s is not a valid GIF File", FPTR_PATH);
                  
     return Data_Wrap_Struct(klass,0,free_img,iptr);
 }
@@ -125,7 +145,7 @@
 img_from_gif(klass, f)
     VALUE klass, f;
 {
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr iptr;
 
     Check_Type(f, T_FILE); 
@@ -133,9 +153,9 @@
     GetOpenFile(f, fptr);
     rb_io_check_readable(fptr);
 
-    iptr = gdImageCreateFromGif(fdopen(fptr->fd, "r"));
+    iptr = gdImageCreateFromGif(FILE_POINTER_FOR_CREATE_FROM);
     if (!iptr)
-        rb_raise(rb_eArgError, "%s is not a valid GIF File", (char*)fptr->pathv);
+        rb_raise(rb_eArgError, "%s is not a valid GIF File", FPTR_PATH);
                  
     return Data_Wrap_Struct(klass,0,free_img,iptr);
 }
@@ -146,7 +166,7 @@
     VALUE klass, fname;
 {
     VALUE f;
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr iptr;
     
     Check_Type(fname, T_STRING);
@@ -156,9 +176,9 @@
     GetOpenFile(f, fptr);
     rb_io_check_readable(fptr);
 
-    iptr = gdImageCreateFromGd(fdopen(fptr->fd, "r"));
+    iptr = gdImageCreateFromGd(FILE_POINTER_FOR_CREATE_FROM);
     if (!iptr)
-        rb_raise(rb_eArgError, "%s is not a valid Gd File", (char*)fptr->pathv);
+        rb_raise(rb_eArgError, "%s is not a valid Gd File", FPTR_PATH);
                  
     return Data_Wrap_Struct(klass,0,free_img,iptr);
 }
@@ -167,7 +187,7 @@
 img_from_gd(klass, f)
     VALUE klass, f;
 {
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr iptr;
 
     Check_Type(f, T_FILE); 
@@ -175,9 +195,9 @@
     GetOpenFile(f, fptr);
     rb_io_check_readable(fptr);
 
-    iptr = gdImageCreateFromGd(fdopen(fptr->fd, "r"));
+    iptr = gdImageCreateFromGd(FILE_POINTER_FOR_CREATE_FROM);
     if (!iptr)
-        rb_raise(rb_eArgError, "%s is not a valid Gd File", (char*)fptr->pathv);
+        rb_raise(rb_eArgError, "%s is not a valid Gd File", FPTR_PATH);
     return Data_Wrap_Struct(klass,0,free_img,iptr);
 }
 
@@ -186,7 +206,7 @@
     VALUE klass, fname;
 {
     VALUE f;
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr iptr;
     
     Check_Type(fname, T_STRING);
@@ -196,9 +216,9 @@
     GetOpenFile(f, fptr);
     rb_io_check_readable(fptr);
 
-    iptr = gdImageCreateFromGd2(fdopen(fptr->fd, "r"));
+    iptr = gdImageCreateFromGd2(FILE_POINTER_FOR_CREATE_FROM);
     if (!iptr)
-        rb_raise(rb_eArgError, "%s is not a valid Gd2 File", (char*)fptr->pathv);
+        rb_raise(rb_eArgError, "%s is not a valid Gd2 File", FPTR_PATH);
                  
     return Data_Wrap_Struct(klass,0,free_img,iptr);
 }
@@ -207,7 +227,7 @@
 img_from_gd2(klass, f)
     VALUE klass, f;
 {
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr iptr;
 
     Check_Type(f, T_FILE);
@@ -215,9 +235,9 @@
     GetOpenFile(f, fptr);
     rb_io_check_readable(fptr);
 
-    iptr = gdImageCreateFromGd2(fdopen(fptr->fd, "r"));
+    iptr = gdImageCreateFromGd2(FILE_POINTER_FOR_CREATE_FROM);
     if (!iptr)
-        rb_raise(rb_eArgError, "%s is not a valid Gd2 File", (char*)fptr->pathv);
+        rb_raise(rb_eArgError, "%s is not a valid Gd2 File", FPTR_PATH);
     
     return Data_Wrap_Struct(klass,0,free_img,iptr);
 }
@@ -227,7 +247,7 @@
     VALUE klass, fname, srcx, srcy, w, h;
 {
     VALUE f;
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr iptr;
     
     Check_Type(fname, T_STRING);
@@ -237,10 +257,10 @@
     GetOpenFile(f, fptr);
     rb_io_check_readable(fptr);
 
-    iptr = gdImageCreateFromGd2Part(fdopen(fptr->fd, "r"), NUM2INT(srcx),
+    iptr = gdImageCreateFromGd2Part(FILE_POINTER_FOR_CREATE_FROM, NUM2INT(srcx),
                                     NUM2INT(srcy), NUM2INT(w), NUM2INT(h));
     if (!iptr)
-        rb_raise(rb_eArgError, "%s is not a valid Gd2 File", (char*)fptr->pathv);
+        rb_raise(rb_eArgError, "%s is not a valid Gd2 File", FPTR_PATH);
                  
     return Data_Wrap_Struct(klass,0,free_img,iptr);
 }
@@ -249,7 +269,7 @@
 img_from_gd2_part(klass, f, srcx, srcy, w, h)
     VALUE klass, f, srcx, srcy, w, h;
 {
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr iptr;
 
     Check_Type(f, T_FILE);
@@ -257,10 +277,10 @@
     GetOpenFile(f, fptr);
     rb_io_check_readable(fptr);
 
-    iptr = gdImageCreateFromGd2Part(fdopen(fptr->fd, "r"), NUM2INT(srcx),
+    iptr = gdImageCreateFromGd2Part(FILE_POINTER_FOR_CREATE_FROM, NUM2INT(srcx),
                                    NUM2INT(srcy), NUM2INT(w), NUM2INT(h));
     if (!iptr)
-        rb_raise(rb_eArgError, "%s is not a valid Gd2 File", (char*)fptr->pathv);
+        rb_raise(rb_eArgError, "%s is not a valid Gd2 File", FPTR_PATH);
     
     return Data_Wrap_Struct(klass,0,free_img,iptr);
 }
@@ -270,7 +290,7 @@
 img_from_xbm(klass, f)
     VALUE klass, f;
 {
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr iptr;
 
     Check_Type(f, T_FILE); 
@@ -278,9 +298,9 @@
     GetOpenFile(f, fptr);
     rb_io_check_readable(fptr);
 
-    iptr = gdImageCreateFromXbm(fdopen(fptr->fd, "r"));
+    iptr = gdImageCreateFromXbm(FILE_POINTER_FOR_CREATE_FROM);
     if (!iptr)
-        rb_raise(rb_eArgError, "%s is not a valid Xbm File", (char*)fptr->pathv);
+        rb_raise(rb_eArgError, "%s is not a valid Xbm File", FPTR_PATH);
 
     return Data_Wrap_Struct(klass,0,free_img,iptr);
 }
@@ -290,7 +310,7 @@
     VALUE klass, fname;
 {
     VALUE f;
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr iptr;
     
     Check_Type(fname, T_STRING);
@@ -300,9 +320,9 @@
     GetOpenFile(f, fptr);
     rb_io_check_readable(fptr);
 
-    iptr = gdImageCreateFromXbm(fdopen(fptr->fd, "r"));
+    iptr = gdImageCreateFromXbm(FILE_POINTER_FOR_CREATE_FROM);
     if (!iptr)
-        rb_raise(rb_eArgError, "%s is not a valid Xbm File", (char*)fptr->pathv);
+        rb_raise(rb_eArgError, "%s is not a valid Xbm File", FPTR_PATH);
                  
     return Data_Wrap_Struct(klass,0,free_img,iptr);
 }
@@ -312,7 +332,7 @@
 img_from_xpm(klass, f)
     VALUE klass, f;
 {
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr iptr;
 
     Check_Type(f, T_FILE);
@@ -321,9 +341,9 @@
     rb_io_check_readable(fptr);
 
     /* need cast, and the argument is char* type */
-    iptr = (gdImagePtr)gdImageCreateFromXpm(fptr->path);
+    iptr = (gdImagePtr)gdImageCreateFromXpm(FPTR_PATH);
     if (!iptr)
-        rb_raise(rb_eArgError, "%s is not a valid XPM File", (char*)fptr->path);
+        rb_raise(rb_eArgError, "%s is not a valid XPM File", (char*)FPTR_PATH);
 
     return Data_Wrap_Struct(klass,0,free_img,iptr);
 }
@@ -333,7 +353,7 @@
     VALUE klass, fname;
 {
     VALUE f;
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr iptr;
     
     Check_Type(fname, T_STRING);
@@ -344,9 +364,9 @@
     rb_io_check_readable(fptr);
 
     /* need cast, and the argument is char* type */
-    iptr = (gdImagePtr)gdImageCreateFromXpm(fptr->path);
+    iptr = (gdImagePtr)gdImageCreateFromXpm(FPTR_PATH);
     if (!iptr)
-        rb_raise(rb_eArgError, "%s is not a valid XPM File", (char*)fptr->path);
+        rb_raise(rb_eArgError, "%s is not a valid XPM File", (char*)FPTR_PATH);
                  
     return Data_Wrap_Struct(klass,0,free_img,iptr);
 }
@@ -358,7 +378,7 @@
 img_from_jpeg(klass, f)
     VALUE klass, f;
 {
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr iptr;
 
     Check_Type(f, T_FILE);
@@ -366,9 +386,9 @@
     GetOpenFile(f, fptr);
     rb_io_check_readable(fptr);
     
-    iptr = gdImageCreateFromJpeg(fdopen(fptr->fd, "r"));
+    iptr = gdImageCreateFromJpeg(FILE_POINTER_FOR_CREATE_FROM);
     if (!iptr)
-        rb_raise(rb_eArgError, "%s is not a valid Jpeg File", (char*)fptr->pathv);
+        rb_raise(rb_eArgError, "%s is not a valid Jpeg File", FPTR_PATH);
 
     return Data_Wrap_Struct(klass,0,free_img,iptr);
 }
@@ -378,7 +398,7 @@
     VALUE klass, fname;
 {
     VALUE f;
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr iptr;
     
     Check_Type(fname, T_STRING);
@@ -388,9 +408,9 @@
     GetOpenFile(f, fptr);
     rb_io_check_readable(fptr);
 
-    iptr = gdImageCreateFromJpeg(fdopen(fptr->fd, "r"));
+    iptr = gdImageCreateFromJpeg(FILE_POINTER_FOR_CREATE_FROM);
     if (!iptr)
-        rb_raise(rb_eArgError, "%s is not a valid Jpeg File", (char*)fptr->pathv);
+        rb_raise(rb_eArgError, "%s is not a valid Jpeg File", FPTR_PATH);
                  
     return Data_Wrap_Struct(klass,0,free_img,iptr);
 }
@@ -1498,7 +1518,7 @@
     VALUE img, out;
 {
     gdImagePtr im;
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     FILE *f;
 
     Data_Get_Struct(img, gdImage, im);
@@ -1507,7 +1527,7 @@
     GetOpenFile(out, fptr);
     rb_io_check_writable(fptr);
 
-    f = rb_io_stdio_file(fptr);
+    f = SECOND_FILE_POINTER;
     gdImagePng(im, f);
 
     return img;
@@ -1542,7 +1562,7 @@
     VALUE img, out;
 {
     gdImagePtr im;
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     FILE *f;
 
     Data_Get_Struct(img, gdImage, im);
@@ -1581,7 +1601,7 @@
     VALUE img, out;
 {
     gdImagePtr im;
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     FILE *f;
 
     Data_Get_Struct(img, gdImage, im);
@@ -1589,7 +1609,7 @@
     rb_io_binmode(out);
     GetOpenFile(out, fptr);
     rb_io_check_writable(fptr);
-    f = rb_io_stdio_file(fptr);
+    f = SECOND_FILE_POINTER;
 
     gdImageGd(im, f);
 
@@ -1600,7 +1620,7 @@
 img_gd2(img, out, cs, fmt)
     VALUE img, out, cs, fmt;
 {
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     gdImagePtr im;
     FILE *f;
 
@@ -1608,7 +1628,7 @@
     rb_io_binmode(out);
     GetOpenFile(out, fptr);
     rb_io_check_writable(fptr);
-    f = rb_io_stdio_file(fptr);
+    f = SECOND_FILE_POINTER;
 
     Data_Get_Struct(img, gdImage, im);
     gdImageGd2(im, f, NUM2INT(cs), NUM2INT(fmt));
@@ -1623,7 +1643,7 @@
     VALUE img, out, quality;
 {
     gdImagePtr im;
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     FILE *f;
 
     Data_Get_Struct(img, gdImage, im);
@@ -1633,7 +1653,7 @@
     rb_io_binmode(out);
     GetOpenFile(out, fptr);
     rb_io_check_writable(fptr);
-    f = rb_io_stdio_file(fptr);
+    f = SECOND_FILE_POINTER;
 
     gdImageJpeg(im, f, FIX2INT(quality));
 
@@ -1668,7 +1688,7 @@
     VALUE img, out, fg;
 {
     gdImagePtr im;
-    rb_io_t *fptr;
+    FPTR_TYPE *fptr;
     FILE *f;
 
     Data_Get_Struct(img, gdImage, im);
@@ -1678,7 +1698,7 @@
     rb_io_binmode(out);
     GetOpenFile(out, fptr);
     rb_io_check_writable(fptr);
-    f = rb_io_stdio_file(fptr);
+    f = SECOND_FILE_POINTER;
 
     gdImageWBMP(im, FIX2INT(fg), f);
 
--- a/extconf.rb
+++ b/extconf.rb
@@ -24,7 +24,11 @@
 
 dir_config("gd", "/usr/local/include", "/usr/local/lib")
 
+have_header('ruby/io.h')
 
+if have_type("rb_io_t", ["ruby.h", "rubyio.h"])
+  have_struct_member("rb_io_t", "fd", ["ruby.h", "rubyio.h"])
+end
 
 if with_config("xpm")
   dir_config("X11", "/usr/X11R6/include", "/usr/X11R6/lib")
