fxruby 1.6.29 → 1.6.30

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/History.txt +12 -1
  3. data/Manifest.txt +5 -0
  4. data/Rakefile +8 -2
  5. data/examples/gltest.rb +0 -7
  6. data/examples/groupbox.rb +5 -3
  7. data/examples/thread.rb +55 -0
  8. data/ext/fox16_c/FXRbApp.cpp +67 -5
  9. data/ext/fox16_c/FXRuby.cpp +142 -110
  10. data/ext/fox16_c/extconf.rb +36 -28
  11. data/ext/fox16_c/gvl_wrappers.cpp +12 -0
  12. data/ext/fox16_c/include/FXRbApp.h +41 -6
  13. data/ext/fox16_c/include/FXRbBitmap.h +12 -12
  14. data/ext/fox16_c/include/FXRbCommon.h +3 -0
  15. data/ext/fox16_c/include/FXRbCursor.h +2 -2
  16. data/ext/fox16_c/include/FXRbDC.h +62 -62
  17. data/ext/fox16_c/include/FXRbDialogBox.h +2 -2
  18. data/ext/fox16_c/include/FXRbDockBar.h +3 -3
  19. data/ext/fox16_c/include/FXRbDockSite.h +4 -4
  20. data/ext/fox16_c/include/FXRbDrawable.h +1 -1
  21. data/ext/fox16_c/include/FXRbFileDict.h +3 -3
  22. data/ext/fox16_c/include/FXRbFoldingList.h +28 -28
  23. data/ext/fox16_c/include/FXRbFont.h +18 -18
  24. data/ext/fox16_c/include/FXRbGLCanvas.h +4 -4
  25. data/ext/fox16_c/include/FXRbGLObject.h +8 -8
  26. data/ext/fox16_c/include/FXRbGLShape.h +1 -1
  27. data/ext/fox16_c/include/FXRbGLViewer.h +3 -3
  28. data/ext/fox16_c/include/FXRbHeader.h +7 -7
  29. data/ext/fox16_c/include/FXRbIconList.h +28 -28
  30. data/ext/fox16_c/include/FXRbIconSource.h +12 -12
  31. data/ext/fox16_c/include/FXRbId.h +3 -3
  32. data/ext/fox16_c/include/FXRbImage.h +19 -19
  33. data/ext/fox16_c/include/FXRbList.h +21 -21
  34. data/ext/fox16_c/include/FXRbListBox.h +1 -1
  35. data/ext/fox16_c/include/FXRbMDIChild.h +4 -4
  36. data/ext/fox16_c/include/FXRbMDIClient.h +4 -4
  37. data/ext/fox16_c/include/FXRbObject.h +2 -2
  38. data/ext/fox16_c/include/FXRbPopup.h +2 -2
  39. data/ext/fox16_c/include/FXRbRealSpinner.h +1 -1
  40. data/ext/fox16_c/include/FXRbScrollArea.h +4 -4
  41. data/ext/fox16_c/include/FXRbShutter.h +1 -1
  42. data/ext/fox16_c/include/FXRbSpinner.h +1 -1
  43. data/ext/fox16_c/include/FXRbStream.h +3 -3
  44. data/ext/fox16_c/include/FXRbTabBar.h +1 -1
  45. data/ext/fox16_c/include/FXRbTable.h +53 -53
  46. data/ext/fox16_c/include/FXRbText.h +23 -23
  47. data/ext/fox16_c/include/FXRbTopWindow.h +5 -5
  48. data/ext/fox16_c/include/FXRbTranslator.h +1 -1
  49. data/ext/fox16_c/include/FXRbTreeList.h +28 -28
  50. data/ext/fox16_c/include/FXRbTreeListBox.h +1 -1
  51. data/ext/fox16_c/include/FXRbWindow.h +31 -31
  52. data/ext/fox16_c/include/FXRuby.h +200 -94
  53. data/ext/fox16_c/include/gvl_wrappers.h +594 -0
  54. data/lib/fox16.rb +1 -0
  55. data/lib/fox16/thread.rb +51 -0
  56. data/lib/fox16/version.rb +1 -1
  57. data/rdoc-sources/FXApp.rb +5 -0
  58. data/rdoc-sources/FXId.rb +5 -0
  59. data/swig-interfaces/FXApp.i +14 -78
  60. data/swig-interfaces/macros.i +56 -0
  61. data/test/TC_FXApp.rb +60 -10
  62. data/test/TC_FXJPGImage.rb +47 -0
  63. metadata +24 -103
  64. checksums.yaml.gz.sig +0 -0
  65. data.tar.gz.sig +0 -0
  66. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a837153db759d5d0212ed3bd3309e42ad89198f3
4
- data.tar.gz: 327a4036ff9a20a0a3d912dd3dd83f890c146440
3
+ metadata.gz: 44b2e39e12cd0a4505ff9fec616e40f5d81322bc
4
+ data.tar.gz: fd959fae8d4c541edad0623d6fabe7425b970d1d
5
5
  SHA512:
6
- metadata.gz: 0f4dd7eafac02894f548c425f6a6c3b1409cad15e938518e7515959bfb3253b7f049c0c6872a6fed98909c9997d7a85273d8d0ba5cc815f3bc1aa99929e2425d
7
- data.tar.gz: 23efde821a0d1d4425d7f73c4204cb7da3f428065765f6db3b85dec25a5842bb59a73e43a6a3e66eb0b46372f26760667dfa34e06c9d989a659efaaa7011cbf9
6
+ metadata.gz: 628b2d089d4c7d7ce2f90f7bdc76c946a9201f34baa34d1fa701f4b4170b94350a5fca793448e17a2cc2906ff507bbaf73c1dcbb0c6a5f01c342bb0d1aa24161
7
+ data.tar.gz: b2e9ea0afd3973803a463188bdec4ae94fd16ab62c9f8c19e3fea4d95c39306aff1d9aa36a0dad50e22868fa385cb408684dc1d664a4caa66fb0e40f4d2329bc
data/History.txt CHANGED
@@ -1,4 +1,15 @@
1
- === 1.6.29 / 2015-02-16
1
+ === 1.6.30 / 2015-07-07
2
+
3
+ * Fix crashes in rb_gc_mark(): 0x00000003f54af8 is T_ZOMBIE / T_NONE
4
+ * Release Ruby's GVL while calls to FXImage#savePixels, #loadPixels
5
+ and FXApp#run* methods.
6
+ * Add a working version for FXApp#addInput event handling on Windows.
7
+ This works for sockets only for now.
8
+ * Add FXApp#runOnUiThread and FXId#runOnUiThread .
9
+ This allows to safely execute GUI code from other threads.
10
+ * Use rake-compiler-dock for building windows binary gems.
11
+
12
+ === 1.6.29 / 2015-02-17
2
13
 
3
14
  * Add Windows binaries for Ruby-2.1 and 2.2.
4
15
  * Use shared libs for Windows binary gems to reduce gem size.
data/Manifest.txt CHANGED
@@ -128,6 +128,7 @@ examples/textedit/commands.rb
128
128
  examples/textedit/helpwindow.rb
129
129
  examples/textedit/prefdialog.rb
130
130
  examples/textedit/textedit.rb
131
+ examples/thread.rb
131
132
  examples/unicode.rb
132
133
  ext/fox16_c/FXRbApp.cpp
133
134
  ext/fox16_c/FXRbDataTarget.cpp
@@ -135,6 +136,7 @@ ext/fox16_c/FXRbGLViewer.cpp
135
136
  ext/fox16_c/FXRuby.cpp
136
137
  ext/fox16_c/MANIFEST
137
138
  ext/fox16_c/extconf.rb
139
+ ext/fox16_c/gvl_wrappers.cpp
138
140
  ext/fox16_c/impl.cpp
139
141
  ext/fox16_c/include/FXMemoryBuffer.h
140
142
  ext/fox16_c/include/FXRb4Splitter.h
@@ -357,6 +359,7 @@ ext/fox16_c/include/FXRbXBMImage.h
357
359
  ext/fox16_c/include/FXRbXPMIcon.h
358
360
  ext/fox16_c/include/FXRbXPMImage.h
359
361
  ext/fox16_c/include/FXRuby.h
362
+ ext/fox16_c/include/gvl_wrappers.h
360
363
  ext/fox16_c/include/impl.h
361
364
  ext/fox16_c/make_impl.rb
362
365
  ext/fox16_c/markfuncs.cpp
@@ -675,6 +678,7 @@ lib/fox16/scintilla.rb
675
678
  lib/fox16/settings.rb
676
679
  lib/fox16/signal.rb
677
680
  lib/fox16/splashscreen.rb
681
+ lib/fox16/thread.rb
678
682
  lib/fox16/timeout.rb
679
683
  lib/fox16/tkcompat.rb
680
684
  lib/fox16/undolist.rb
@@ -1142,6 +1146,7 @@ test/TC_FXIconDict.rb
1142
1146
  test/TC_FXIconList.rb
1143
1147
  test/TC_FXId.rb
1144
1148
  test/TC_FXImage.rb
1149
+ test/TC_FXJPGImage.rb
1145
1150
  test/TC_FXLight.rb
1146
1151
  test/TC_FXList.rb
1147
1152
  test/TC_FXListBox.rb
data/Rakefile CHANGED
@@ -21,7 +21,6 @@ PKG_VERSION = Fox.fxrubyversion
21
21
 
22
22
  SWIG = (RUBY_PLATFORM =~ /mingw/) ? "swig.exe" : "swig"
23
23
  SWIGFLAGS = "-c++ -ruby -nodefaultdtor -nodefaultctor -w302 -features compactdefaultargs -I../fox-includes"
24
- SWIG_LIB = `#{SWIG} -swiglib`.chomp
25
24
  SWIG_MODULES = {
26
25
  "core.i" => "core_wrap.cpp",
27
26
  "dcmodule.i" => "dc_wrap.cpp",
@@ -47,7 +46,7 @@ SWIG_MODULES = {
47
46
  hoe = Hoe.spec "fxruby" do
48
47
  # ... project specific data ...
49
48
  self.blog_categories = %w{FXRuby}
50
- self.clean_globs = [".config", "ext/fox16_c/Makefile", "ext/fox16_c/*.o", "ext/fox16_c/*.bundle", "ext/fox16_c/mkmf.log", "ext/fox16_c/conftest.dSYM", "ext/fox16_c/include/swigrubyrun.h", "ext/fox16_c/librb.c", "ext/fox16_c/include/inlinestubs.h", "ext/fox16_c/*_wrap.cpp"]
49
+ self.clean_globs = [".config", "ext/fox16_c/Makefile", "ext/fox16_c/*.o", "ext/fox16_c/*.bundle", "ext/fox16_c/mkmf.log", "ext/fox16_c/conftest.dSYM", "ext/fox16_c/include/swigrubyrun.h", "ext/fox16_c/librb.c", "ext/fox16_c/include/inlinestubs.h", "ext/fox16_c/*_wrap.cpp", "tmp", "ports/*.installed", "ports/*mingw32*"]
51
50
  developer("Lyle Johnson", "lyle@lylejohnson.name")
52
51
  developer("Lars Kanis", "kanis@comcard.de")
53
52
  self.extra_rdoc_files = ["rdoc-sources", File.join("rdoc-sources", "README.rdoc")]
@@ -63,6 +62,7 @@ hoe = Hoe.spec "fxruby" do
63
62
  self.version = PKG_VERSION
64
63
  self.readme_file = 'README.rdoc'
65
64
  self.extra_rdoc_files << self.readme_file
65
+ self.extra_deps << ['mini_portile', '~> 0.6']
66
66
 
67
67
  spec_extras[:files] = File.read_utf("Manifest.txt").split(/\r?\n\r?/).reject{|f| f=~/^fox-includes|^web/ }
68
68
  spec_extras[:files] += SWIG_MODULES.values.map{|f| File.join("ext/fox16_c", f) }
@@ -126,6 +126,12 @@ ENV['RUBY_CC_VERSION'].to_s.split(':').each do |ruby_version|
126
126
  end
127
127
  end
128
128
 
129
+ desc "Build the windows binary gems"
130
+ task 'gem:windows' => 'gem' do
131
+ require 'rake_compiler_dock'
132
+ RakeCompilerDock.sh "rake cross native gem RUBYOPT=--disable-rubygems MAKE=\"nice make V=1 -j `nproc`\" "
133
+ end
134
+
129
135
  # Set environment variable SWIG_LIB to
130
136
  # c:/ruby-1.8.6-p383-preview2/devkit/msys/1.0.11/usr/local/share/swig/1.3.22
131
137
  # before running swig on MinGW.
data/examples/gltest.rb CHANGED
@@ -312,13 +312,6 @@ if __FILE__ == $0
312
312
  # Construct the application
313
313
  application = FXApp.new("GLTest", "FoxTest")
314
314
 
315
- # To ensure that the chores-based spin will run as fast as possible,
316
- # we can disable the chore in FXRuby's event loop that tries to schedule
317
- # other threads. This is OK for this program because there aren't any
318
- # other Ruby threads running.
319
-
320
- application.disableThreads
321
-
322
315
  # Construct the main window
323
316
  GLTestWindow.new(application)
324
317
 
data/examples/groupbox.rb CHANGED
@@ -361,12 +361,14 @@ class GroupWindow < FXMainWindow
361
361
  show(PLACEMENT_SCREEN)
362
362
 
363
363
  # Create a thread to update the clock
364
- @clockThread = Thread.new(@clockLabel) { |clockLabel|
364
+ @clockThread = Thread.new(@clockLabel) do |clockLabel|
365
365
  while true
366
- clockLabel.text = Time.now.strftime("%I:%M:%S %p")
366
+ runOnUiThread do
367
+ clockLabel.text = Time.now.strftime("%I:%M:%S %p")
368
+ end
367
369
  sleep(1)
368
370
  end
369
- }
371
+ end
370
372
  end
371
373
  end
372
374
 
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'fox16'
4
+
5
+ class ThreadedWindow < Fox::FXMainWindow
6
+ include Fox
7
+
8
+ def initialize(app)
9
+ # Call the base class initializer first
10
+ super(app, "Threaded Widget Test", :opts => DECOR_ALL, width: 200, height: 500)
11
+
12
+ @vframe = FXVerticalFrame.new(self,
13
+ FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y, :padding => 0) do |frame|
14
+ FXButton.new(frame, "Klick to add", opts: FRAME_RAISED|FRAME_THICK|LAYOUT_FILL_X) do |button|
15
+ button.connect(SEL_COMMAND, method(:on_button_clicked))
16
+ end
17
+ end
18
+ end
19
+
20
+ def on_button_clicked(sender, sel, ptr)
21
+ FXHorizontalFrame.new(@vframe,
22
+ FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y, :padding => 10) do |frame|
23
+
24
+ label = FXLabel.new frame, "..."
25
+
26
+ Thread.new do
27
+ 50.times do |seconds|
28
+ runOnUiThread do
29
+ label.text = "#{(50 - seconds)/10.0} seconds to remove"
30
+ end
31
+ sleep 0.1
32
+ end
33
+
34
+ runOnUiThread do
35
+ @vframe.removeChild(frame)
36
+ @vframe.create; @vframe.show; @vframe.recalc
37
+ end
38
+ end
39
+ end
40
+ @vframe.create; @vframe.show; @vframe.recalc
41
+ end
42
+
43
+ # Create and show this window
44
+ def create
45
+ super
46
+ show(PLACEMENT_SCREEN)
47
+ end
48
+ end
49
+
50
+ if __FILE__ == $0
51
+ application = Fox::FXApp.new("ThreadApp", "FoxTest")
52
+ ThreadedWindow.new(application)
53
+ application.create
54
+ application.run
55
+ end
@@ -36,19 +36,31 @@ extern "C" {
36
36
  #include <sys/time.h> /* For struct timeval */
37
37
  #endif
38
38
 
39
+ #ifndef WIN32
40
+ #include <fcntl.h>
41
+ #endif
42
+
39
43
  // Message map
40
44
  FXDEFMAP(FXRbApp) FXRbAppMap[]={
45
+ #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
46
+ FXMAPFUNC(SEL_IO_READ,FXRbApp::ID_CHORE_THREADS,FXRbApp::onChoreThreads),
47
+ #else
41
48
  FXMAPFUNC(SEL_CHORE,FXRbApp::ID_CHORE_THREADS,FXRbApp::onChoreThreads),
49
+ #endif
42
50
  };
43
51
 
44
52
  // Class implementation
45
53
  FXRbIMPLEMENT(FXRbApp,FXApp,FXRbAppMap,ARRAYNUMBER(FXRbAppMap))
46
54
 
55
+ #ifdef WIN32
56
+ WSAEVENT FXRbApp::interrupt_event = NULL;
57
+ #else
58
+ int FXRbApp::interrupt_fds[2] = {-1, -1};
59
+ #endif
60
+
47
61
  // Constructor
48
- FXRbApp::FXRbApp(const FXchar* appname,const FXchar* vendor) : FXApp(appname,vendor),m_bThreadsEnabled(TRUE),sleepTime(100){
49
- if(m_bThreadsEnabled){
50
- addChore(this,ID_CHORE_THREADS);
51
- }
62
+ FXRbApp::FXRbApp(const FXchar* appname,const FXchar* vendor) : FXApp(appname,vendor),m_bThreadsEnabled(FALSE),sleepTime(100){
63
+ setThreadsEnabled(TRUE);
52
64
  }
53
65
 
54
66
 
@@ -67,12 +79,33 @@ void FXRbApp::setThreadsEnabled(FXbool enabled){
67
79
  if(enabled){
68
80
  if(!m_bThreadsEnabled){
69
81
  m_bThreadsEnabled=TRUE;
82
+ #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
83
+ #ifdef WIN32
84
+ interrupt_event = CreateEvent(NULL, TRUE, FALSE, NULL);
85
+ addInput(interrupt_event,INPUT_READ,this,ID_CHORE_THREADS);
86
+ #else
87
+ pipe2(interrupt_fds, O_NONBLOCK);
88
+ addInput(interrupt_fds[0],INPUT_READ,this,ID_CHORE_THREADS);
89
+ #endif
90
+ #else
70
91
  addChore(this,ID_CHORE_THREADS);
92
+ #endif
71
93
  }
72
94
  }
73
95
  else{
74
96
  m_bThreadsEnabled=FALSE;
97
+ #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
98
+ #ifdef WIN32
99
+ removeInput(interrupt_event,INPUT_READ);
100
+ CloseHandle(interrupt_event); interrupt_event = NULL;
101
+ #else
102
+ removeInput(interrupt_fds[0],INPUT_READ);
103
+ close(interrupt_fds[0]); interrupt_fds[0] = -1;
104
+ close(interrupt_fds[1]); interrupt_fds[1] = -1;
105
+ #endif
106
+ #else
75
107
  removeChore(this,ID_CHORE_THREADS);
108
+ #endif
76
109
  }
77
110
  }
78
111
 
@@ -88,9 +121,27 @@ FXuint FXRbApp::getSleepTime() const {
88
121
  return sleepTime;
89
122
  }
90
123
 
124
+ long FXRbApp::onChoreThreads(FXObject *obj,FXSelector sel,void *p){
125
+ #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
126
+ #ifdef WIN32
127
+ ResetEvent(interrupt_event);
128
+ #else
129
+ char byte;
130
+ // clear the pipe
131
+ read(interrupt_fds[0], &byte, 1);
132
+ #endif
133
+ #endif
134
+ return FXRbApp_onChoreThreads(this, obj, sel, p);
135
+ }
136
+
137
+ long FXRbApp_onChoreThreads_gvlcb(FXRbApp *self,FXObject *obj,FXSelector sel,void *p){
138
+ return self->onChoreThreads_gvlcb(obj, sel, p);
139
+ }
91
140
 
92
141
  // Process threads
93
- long FXRbApp::onChoreThreads(FXObject*,FXSelector,void*){
142
+ long FXRbApp::onChoreThreads_gvlcb(FXObject*,FXSelector,void*){
143
+ #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
144
+ #else
94
145
  // Pause for 'sleepTime' millseconds
95
146
  struct timeval wait;
96
147
  wait.tv_sec=0;
@@ -108,16 +159,27 @@ long FXRbApp::onChoreThreads(FXObject*,FXSelector,void*){
108
159
 
109
160
  // Re-register this chore for next time
110
161
  addChore(this,ID_CHORE_THREADS);
162
+ #endif
111
163
 
112
164
  // Back to work...
113
165
  return 1;
114
166
  }
115
167
 
168
+ #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
169
+ void fxrb_wakeup_fox(void *){
170
+ #ifdef WIN32
171
+ SetEvent(FXRbApp::interrupt_event);
172
+ #else
173
+ write(FXRbApp::interrupt_fds[1], "X", 1);
174
+ #endif
175
+ }
176
+ #endif
116
177
 
117
178
  // Destructor
118
179
  FXRbApp::~FXRbApp(){
119
180
  FXTRACE((100,"FXRbApp::~FXRbApp()\n"));
120
181
  VALUE myRegistry;
182
+ setThreadsEnabled(FALSE);
121
183
  FXRbDestroyAppSensitiveObjects();
122
184
  myRegistry=FXRbGetRubyObj(&(reg()),true);
123
185
  if(!NIL_P(myRegistry)){
@@ -115,7 +115,7 @@ VALUE FXRbNewPointerObj(void *ptr,swig_type_info* ty){
115
115
  FXRubyObjDesc *desc;
116
116
  if(FXMALLOC(&desc,FXRubyObjDesc,1)){
117
117
  obj=SWIG_Ruby_NewPointerObj(ptr,ty,1);
118
- FXTRACE((1,"FXRbNewPointerObj(rubyObj=%d,foxObj=%p)\n",static_cast<int>(obj),ptr));
118
+ FXTRACE((1,"FXRbNewPointerObj(foxObj=%p) => rubyObj=%p (%s)\n",ptr,(void *)obj,rb_obj_classname(obj)));
119
119
  desc->obj=obj;
120
120
  desc->borrowed=true;
121
121
  desc->in_gc=false;
@@ -185,23 +185,38 @@ void* FXRbConvertPtr(VALUE obj,swig_type_info* ty){
185
185
  FXbool FXRbCatchExceptions=FALSE;
186
186
 
187
187
  // Returns an FXInputHandle for this Ruby file object
188
- FXInputHandle FXRbGetReadFileHandle(VALUE obj) {
188
+ FXInputHandle FXRbGetReadFileHandle(VALUE obj,FXuint mode) {
189
189
  int fd;
190
190
  fd = FIX2INT(rb_funcall(obj, rb_intern("fileno"), 0));
191
191
  #ifdef WIN32
192
192
  #ifdef __CYGWIN__
193
193
  return (FXInputHandle) get_osfhandle(fd);
194
194
  #else
195
- return (FXInputHandle) _get_osfhandle(fd);
195
+ WSAEVENT hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
196
+ long events = 0;
197
+ if(mode&INPUT_READ) events |= FD_READ|FD_ACCEPT|FD_OOB;
198
+ if(mode&INPUT_EXCEPT) events |= FD_CLOSE|FD_QOS|FD_GROUP_QOS|FD_ROUTING_INTERFACE_CHANGE|FD_ADDRESS_LIST_CHANGE;
199
+ if ( WSAEventSelect(_get_osfhandle(fd), hEvent, events) == SOCKET_ERROR ) {
200
+ WSACloseEvent( hEvent );
201
+ rb_raise( rb_eRuntimeError, "WSAEventSelect sockett error: %d", WSAGetLastError() );
202
+ }
203
+ rb_iv_set(obj, "FXRuby::FXRbGetReadFileHandle", ULL2NUM((intptr_t)hEvent));
204
+ return (FXInputHandle) hEvent;
196
205
  #endif
197
206
  #else
198
207
  return (FXInputHandle) fd;
199
208
  #endif
200
209
  }
201
210
 
211
+ void FXRbRemoveReadFileHandle(VALUE obj,FXuint mode) {
212
+ #ifdef WIN32
213
+ WSAEVENT hEvent = (HANDLE)NUM2ULL(rb_iv_get(obj, "FXRuby::FXRbGetReadFileHandle"));
214
+ CloseHandle( hEvent );
215
+ #endif
216
+ }
202
217
 
203
218
  // Returns an FXInputHandle for this Ruby file object
204
- FXInputHandle FXRbGetWriteFileHandle(VALUE obj) {
219
+ FXInputHandle FXRbGetWriteFileHandle(VALUE obj,FXuint mode) {
205
220
  int fd;
206
221
  #if defined(RUBINIUS)
207
222
  VALUE vwrite = rb_intern("@write");
@@ -223,20 +238,36 @@ FXInputHandle FXRbGetWriteFileHandle(VALUE obj) {
223
238
  #ifdef __CYGWIN__
224
239
  return (FXInputHandle) get_osfhandle(fd);
225
240
  #else
226
- return (FXInputHandle) _get_osfhandle(fd);
241
+ WSAEVENT hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
242
+ long events = 0;
243
+ if(mode&INPUT_WRITE) events |= FD_WRITE|FD_CONNECT;
244
+ if(mode&INPUT_EXCEPT) events |= FD_CLOSE|FD_QOS|FD_GROUP_QOS|FD_ROUTING_INTERFACE_CHANGE|FD_ADDRESS_LIST_CHANGE;
245
+ if ( WSAEventSelect(_get_osfhandle(fd), hEvent, events) == SOCKET_ERROR ) {
246
+ WSACloseEvent( hEvent );
247
+ rb_raise( rb_eRuntimeError, "WSAEventSelect sockettt error: %d", WSAGetLastError() );
248
+ }
249
+ rb_iv_set(obj, "FXRuby::FXRbGetWriteFileHandle", ULL2NUM((intptr_t)hEvent));
250
+ return (FXInputHandle) hEvent;
227
251
  #endif
228
252
  #else
229
253
  return (FXInputHandle) fd;
230
254
  #endif
231
255
  }
232
256
 
257
+ void FXRbRemoveWriteFileHandle(VALUE obj,FXuint mode) {
258
+ #ifdef WIN32
259
+ WSAEVENT hEvent = (HANDLE)NUM2ULL(rb_iv_get(obj, "FXRuby::FXRbGetWriteFileHandle"));
260
+ CloseHandle( hEvent );
261
+ #endif
262
+ }
263
+
233
264
 
234
265
  // Register this Ruby class instance
235
266
  void FXRbRegisterRubyObj(VALUE rubyObj,const void* foxObj) {
236
267
  FXASSERT(!NIL_P(rubyObj));
237
268
  FXASSERT(foxObj!=0);
238
269
  FXRubyObjDesc* desc;
239
- FXTRACE((1,"FXRbRegisterRubyObj(rubyObj=%d,foxObj=%p)\n",static_cast<int>(rubyObj),foxObj));
270
+ FXTRACE((1,"FXRbRegisterRubyObj(rubyObj=%p (%s),foxObj=%p)\n",(void *)rubyObj,rb_obj_classname(rubyObj),foxObj));
240
271
  if(st_lookup(FXRuby_Objects,reinterpret_cast<st_data_t>(const_cast<void*>(foxObj)),reinterpret_cast<st_data_t *>(&desc))!=0){
241
272
  FXASSERT(desc->borrowed);
242
273
  /* There is already a Ruby object registered for this foxObj.
@@ -269,10 +300,15 @@ void FXRbRegisterRubyObj(VALUE rubyObj,const void* foxObj) {
269
300
  * Remove this mapping between a Ruby instance and a C++ object
270
301
  */
271
302
  void FXRbUnregisterRubyObj(const void* foxObj){
303
+ FXRbUnregisterRubyObj2(foxObj, true);
304
+ }
305
+
306
+ void FXRbUnregisterRubyObj2(const void* foxObj, bool alsoOwned){
272
307
  if(foxObj!=0){
273
308
  FXRubyObjDesc* desc;
274
309
  if(st_lookup(FXRuby_Objects,reinterpret_cast<st_data_t>(const_cast<void*>(foxObj)),reinterpret_cast<st_data_t *>(&desc))!=0){
275
- FXTRACE((1,"FXRbUnregisterRubyObj(rubyObj=%d,foxObj=%p)\n",static_cast<int>(desc->obj),foxObj));
310
+ if( !alsoOwned && !desc->borrowed ) return;
311
+ FXTRACE((1,"FXRbUnregisterRubyObj(rubyObj=%p (%s),foxObj=%p)\n",(void *)desc->obj,rb_obj_classname(desc->obj),foxObj));
276
312
  DATA_PTR(desc->obj)=0;
277
313
  FXFREE(&desc);
278
314
  st_delete(FXRuby_Objects,reinterpret_cast<st_data_t *>(const_cast<void**>(&foxObj)),reinterpret_cast<st_data_t *>(0));
@@ -281,6 +317,22 @@ void FXRbUnregisterRubyObj(const void* foxObj){
281
317
  }
282
318
  }
283
319
 
320
+ void FXRbUnregisterBorrowedRubyObj(const void* foxObj){
321
+ FXRbUnregisterRubyObj2( foxObj, false );
322
+ };
323
+ void FXRbUnregisterBorrowedRubyObj(FXlong foxObj){
324
+ };
325
+ void FXRbUnregisterBorrowedRubyObj(FXString& foxObj){
326
+ };
327
+ void FXRbUnregisterBorrowedRubyObj(FXRegion& foxObj){
328
+ FXRbUnregisterRubyObj2( &foxObj, false );
329
+ };
330
+ void FXRbUnregisterBorrowedRubyObj(FXRectangle& foxObj){
331
+ FXRbUnregisterRubyObj2( &foxObj, false );
332
+ };
333
+ void FXRbUnregisterBorrowedRubyObj(FXDC& foxObj){
334
+ FXRbUnregisterRubyObj2( &foxObj, false );
335
+ };
284
336
 
285
337
  VALUE to_ruby(const FXObject* obj){
286
338
  if(obj!=0){
@@ -299,20 +351,16 @@ VALUE to_ruby(const FXObject* obj){
299
351
  * Return the registered Ruby class instance associated with this
300
352
  * FOX object, or Qnil if not found.
301
353
  */
302
- VALUE FXRbGetRubyObj(const void *foxObj,bool searchBoth){
354
+ VALUE FXRbGetRubyObj(const void *foxObj,bool alsoBorrowed){
303
355
  FXRubyObjDesc* desc;
304
356
  if(foxObj!=0 && st_lookup(FXRuby_Objects,reinterpret_cast<st_data_t>(const_cast<void*>(foxObj)),reinterpret_cast<st_data_t *>(&desc))!=0){
305
357
  FXASSERT(desc!=0);
306
- if(searchBoth){
358
+ if(alsoBorrowed || !desc->borrowed){
359
+ FXTRACE((2,"FXRbGetRubyObj(foxObj=%p) => rubyObj=%p (%s)\n",foxObj,(void *)desc->obj,rb_obj_classname(desc->obj)));
307
360
  return desc->obj;
308
361
  }
309
- else{
310
- return desc->borrowed ? Qnil : desc->obj;
311
- }
312
- }
313
- else{
314
- return Qnil;
315
362
  }
363
+ return Qnil;
316
364
  }
317
365
 
318
366
  /**
@@ -1229,7 +1277,7 @@ static ID id_assocs;
1229
1277
  * or return zero if the designated receiver doesn't handle this
1230
1278
  * message.
1231
1279
  */
1232
- ID FXRbLookupHandler(FXObject* recv,FXSelector key){
1280
+ ID FXRbLookupHandler_gvlcb(FXObject* recv,FXSelector key){
1233
1281
  FXTRACE((100,"FXRbLookupHandler(recv=%p(%s),FXSEL(%d,%d))\n",recv,recv->getClassName(),FXSELTYPE(key),FXSELID(key)));
1234
1282
  ID id=0;
1235
1283
  VALUE rubyObj=to_ruby(recv);
@@ -1291,7 +1339,7 @@ static VALUE handle_rescue(VALUE args,VALUE error){
1291
1339
 
1292
1340
 
1293
1341
  // Call the designated function and return its result (which should be a long).
1294
- long FXRbHandleMessage(FXObject* recv,ID func,FXObject* sender,FXSelector key,void* ptr){
1342
+ long FXRbHandleMessage_gvlcb(FXObject* recv,ID func,FXObject* sender,FXSelector key,void* ptr){
1295
1343
  FXRbHandleArgs hArgs;
1296
1344
  hArgs.recv=to_ruby(recv);
1297
1345
  hArgs.sender=to_ruby(sender);
@@ -1312,6 +1360,10 @@ long FXRbHandleMessage(FXObject* recv,ID func,FXObject* sender,FXSelector key,vo
1312
1360
  retval=handle_body(reinterpret_cast<VALUE>(&hArgs));
1313
1361
  }
1314
1362
 
1363
+ FXRbUnregisterBorrowedRubyObj(recv);
1364
+ FXRbUnregisterBorrowedRubyObj(sender);
1365
+ FXRbUnregisterBorrowedRubyObj(ptr);
1366
+
1315
1367
  /**
1316
1368
  * Process the return value. For boolean return values, convert "true"
1317
1369
  * to 1 and "false" to zero. For numeric types, convert it to a long value
@@ -1380,70 +1432,70 @@ void FXRbRange2LoHi(VALUE range,FXdouble& lo,FXdouble& hi){
1380
1432
 
1381
1433
  //----------------------------------------------------------------------
1382
1434
 
1383
- void FXRbCallVoidMethod(FXObject* recv, ID func) {
1435
+ void FXRbCallVoidMethod_gvlcb(FXObject* recv, const char *func) {
1384
1436
  VALUE obj=FXRbGetRubyObj(recv,false);
1385
1437
  FXASSERT(!NIL_P(obj));
1386
1438
  FXASSERT(!FXRbIsInGC(recv));
1387
- rb_funcall(obj,func,0,NULL);
1439
+ rb_funcall(obj,rb_intern(func),0,NULL);
1388
1440
  }
1389
1441
 
1390
- void FXRbCallVoidMethod(FXDC* recv,ID func) {
1442
+ void FXRbCallVoidMethod_gvlcb(FXDC* recv,const char *func) {
1391
1443
  VALUE obj=FXRbGetRubyObj(recv,false);
1392
1444
  FXASSERT(!NIL_P(obj));
1393
- rb_funcall(obj,func,0,NULL);
1445
+ rb_funcall(obj,rb_intern(func),0,NULL);
1394
1446
  }
1395
1447
 
1396
1448
  //----------------------------------------------------------------------
1397
1449
 
1398
- bool FXRbCallBoolMethod(const FXObject* recv,ID func){
1450
+ bool FXRbCallBoolMethod_gvlcb(const FXObject* recv,const char *func){
1399
1451
  VALUE obj=FXRbGetRubyObj(recv,false);
1400
1452
  FXASSERT(!NIL_P(obj));
1401
- VALUE v=rb_funcall(obj,func,0,NULL);
1453
+ VALUE v=rb_funcall(obj,rb_intern(func),0,NULL);
1402
1454
  return (v==Qtrue);
1403
1455
  }
1404
1456
 
1405
1457
  //----------------------------------------------------------------------
1406
1458
 
1407
1459
  // Call function with "FXint" return value
1408
- FXint FXRbCallIntMethod(const FXObject* recv,ID func){
1460
+ FXint FXRbCallIntMethod_gvlcb(const FXObject* recv,const char *func){
1409
1461
  VALUE obj=FXRbGetRubyObj(recv,false);
1410
1462
  FXASSERT(!NIL_P(obj));
1411
- VALUE result=rb_funcall(obj,func,0,NULL);
1463
+ VALUE result=rb_funcall(obj,rb_intern(func),0,NULL);
1412
1464
  return static_cast<FXint>(NUM2INT(result));
1413
1465
  }
1414
1466
 
1415
1467
  //----------------------------------------------------------------------
1416
1468
 
1417
1469
  // Call function with "FXGLObject*" return value
1418
- FXGLObject* FXRbCallGLObjectMethod(FXGLObject* recv,ID func){
1470
+ FXGLObject* FXRbCallGLObjectMethod_gvlcb(FXGLObject* recv,const char *func){
1419
1471
  VALUE obj=FXRbGetRubyObj(recv,false);
1420
1472
  FXASSERT(!NIL_P(obj));
1421
- VALUE result=rb_funcall(obj,func,0,NULL);
1473
+ VALUE result=rb_funcall(obj,rb_intern(func),0,NULL);
1422
1474
  return NIL_P(result) ? 0 : reinterpret_cast<FXGLObject*>(DATA_PTR(result));
1423
1475
  }
1424
1476
 
1425
- FXGLObject* FXRbCallGLObjectMethod(FXGLViewer* recv,ID func,FXint x,FXint y){
1477
+ FXGLObject* FXRbCallGLObjectMethod_gvlcb(FXGLViewer* recv,const char *func,FXint x,FXint y){
1426
1478
  VALUE obj=FXRbGetRubyObj(recv,false);
1427
1479
  FXASSERT(!NIL_P(obj));
1428
- VALUE result=rb_funcall(obj,func,2,INT2NUM(x),INT2NUM(y));
1480
+ VALUE result=rb_funcall(obj,rb_intern(func),2,INT2NUM(x),INT2NUM(y));
1429
1481
  return NIL_P(result) ? 0 : reinterpret_cast<FXGLObject*>(DATA_PTR(result));
1430
1482
  }
1431
1483
 
1432
- FXGLObject* FXRbCallGLObjectMethod(FXGLObject* recv,ID func,FXuint* path,FXint n){
1484
+ FXGLObject* FXRbCallGLObjectMethod_gvlcb(FXGLObject* recv,const char *func,FXuint* path,FXint n){
1433
1485
  VALUE obj=FXRbGetRubyObj(recv,false);
1434
1486
  FXASSERT(!NIL_P(obj));
1435
- VALUE result=rb_funcall(obj,func,1,FXRbMakeArray(path,n));
1487
+ VALUE result=rb_funcall(obj,rb_intern(func),1,FXRbMakeArray(path,n));
1436
1488
  return NIL_P(result) ? 0 : reinterpret_cast<FXGLObject*>(DATA_PTR(result));
1437
1489
  }
1438
1490
 
1439
1491
  //----------------------------------------------------------------------
1440
1492
 
1441
1493
  // Call function with "FXGLObject**" return value
1442
- FXGLObject** FXRbCallGLObjectArrayMethod(FXGLViewer* recv,ID func,FXint x,FXint y,FXint w,FXint h){
1494
+ FXGLObject** FXRbCallGLObjectArrayMethod_gvlcb(FXGLViewer* recv,const char *func,FXint x,FXint y,FXint w,FXint h){
1443
1495
  FXGLObject** objects=NULL;
1444
1496
  VALUE obj=FXRbGetRubyObj(recv,false);
1445
1497
  FXASSERT(!NIL_P(obj));
1446
- VALUE result=rb_funcall(obj,func,4,INT2NUM(x),INT2NUM(y),INT2NUM(w),INT2NUM(h));
1498
+ VALUE result=rb_funcall(obj,rb_intern(func),4,INT2NUM(x),INT2NUM(y),INT2NUM(w),INT2NUM(h));
1447
1499
  if(!NIL_P(result)){
1448
1500
  Check_Type(result,T_ARRAY);
1449
1501
  if(FXMALLOC(&objects,FXGLObject*,RARRAY_LEN(result)+1)){
@@ -1458,55 +1510,56 @@ FXGLObject** FXRbCallGLObjectArrayMethod(FXGLViewer* recv,ID func,FXint x,FXint
1458
1510
 
1459
1511
  //----------------------------------------------------------------------
1460
1512
 
1461
- FXTableItem* FXRbCallTableItemMethod(FXTable* recv,ID func,const FXString& text,FXIcon* icon,void* ptr){
1513
+ FXTableItem* FXRbCallTableItemMethod_gvlcb(FXTable* recv,const char *func,const FXString& text,FXIcon* icon,void* ptr){
1462
1514
  VALUE itemData=(ptr==0)?Qnil:reinterpret_cast<VALUE>(ptr);
1463
1515
  VALUE obj=FXRbGetRubyObj(recv,false);
1464
1516
  FXASSERT(!NIL_P(obj));
1465
- VALUE result=rb_funcall(obj,func,3,to_ruby(text),to_ruby(icon),itemData);
1517
+ VALUE result=rb_funcall(obj,rb_intern(func),3,to_ruby(text),to_ruby(icon),itemData);
1518
+ FXRbUnregisterBorrowedRubyObj(icon);
1466
1519
  return NIL_P(result)?0:reinterpret_cast<FXTableItem*>(DATA_PTR(result));
1467
1520
  }
1468
1521
 
1469
- FXTableItem* FXRbCallTableItemMethod(FXTable* recv,ID func,FXint row,FXint col,FXbool notify){
1522
+ FXTableItem* FXRbCallTableItemMethod_gvlcb(FXTable* recv,const char *func,FXint row,FXint col,FXbool notify){
1470
1523
  VALUE obj=FXRbGetRubyObj(recv,false);
1471
1524
  FXASSERT(!NIL_P(obj));
1472
- VALUE result=rb_funcall(obj,func,3,to_ruby(row),to_ruby(col),to_ruby(notify));
1525
+ VALUE result=rb_funcall(obj,rb_intern(func),3,to_ruby(row),to_ruby(col),to_ruby(notify));
1473
1526
  return NIL_P(result)?0:reinterpret_cast<FXTableItem*>(DATA_PTR(result));
1474
1527
  }
1475
1528
 
1476
1529
  //----------------------------------------------------------------------
1477
1530
 
1478
- FXTreeItem* FXRbCallTreeItemMethod(const FXTreeList* recv,ID func,FXint x,FXint y){
1531
+ FXTreeItem* FXRbCallTreeItemMethod_gvlcb(const FXTreeList* recv,const char *func,FXint x,FXint y){
1479
1532
  VALUE obj=FXRbGetRubyObj(recv,false);
1480
1533
  FXASSERT(!NIL_P(obj));
1481
- VALUE result=rb_funcall(obj,func,2,INT2NUM(x),INT2NUM(y));
1534
+ VALUE result=rb_funcall(obj,rb_intern(func),2,INT2NUM(x),INT2NUM(y));
1482
1535
  return NIL_P(result) ? 0 : reinterpret_cast<FXTreeItem*>(DATA_PTR(result));
1483
1536
  }
1484
1537
 
1485
1538
  //----------------------------------------------------------------------
1486
1539
 
1487
- FXFoldingItem* FXRbCallFoldingItemMethod(const FXFoldingList* recv,ID func,FXint x,FXint y){
1540
+ FXFoldingItem* FXRbCallFoldingItemMethod_gvlcb(const FXFoldingList* recv,const char *func,FXint x,FXint y){
1488
1541
  VALUE obj=FXRbGetRubyObj(recv,false);
1489
1542
  FXASSERT(!NIL_P(obj));
1490
- VALUE result=rb_funcall(obj,func,2,INT2NUM(x),INT2NUM(y));
1543
+ VALUE result=rb_funcall(obj,rb_intern(func),2,INT2NUM(x),INT2NUM(y));
1491
1544
  return NIL_P(result) ? 0 : reinterpret_cast<FXFoldingItem*>(DATA_PTR(result));
1492
1545
  }
1493
1546
 
1494
1547
  //----------------------------------------------------------------------
1495
1548
 
1496
- FXFileAssoc* FXRbCallFileAssocMethod(const FXFileDict* recv,ID func,const FXchar* pathname){
1549
+ FXFileAssoc* FXRbCallFileAssocMethod_gvlcb(const FXFileDict* recv,const char *func,const FXchar* pathname){
1497
1550
  VALUE obj=FXRbGetRubyObj(recv,false);
1498
1551
  FXASSERT(!NIL_P(obj));
1499
- VALUE result=rb_funcall(obj,func,1,to_ruby(pathname));
1552
+ VALUE result=rb_funcall(obj,rb_intern(func),1,to_ruby(pathname));
1500
1553
  return NIL_P(result) ? 0 : reinterpret_cast<FXFileAssoc*>(DATA_PTR(result));
1501
1554
  }
1502
1555
 
1503
1556
  //----------------------------------------------------------------------
1504
1557
 
1505
- FXIcon* FXRbCallIconMethod(const FXTableItem* recv,ID func){
1558
+ FXIcon* FXRbCallIconMethod_gvlcb(const FXTableItem* recv,const char *func){
1506
1559
  VALUE obj=FXRbGetRubyObj(recv,false);
1507
1560
  FXASSERT(!NIL_P(obj));
1508
1561
  if(!NIL_P(obj)){
1509
- VALUE result=rb_funcall(obj,func,0,NULL);
1562
+ VALUE result=rb_funcall(obj,rb_intern(func),0,NULL);
1510
1563
  return NIL_P(result) ? 0 : reinterpret_cast<FXIcon*>(DATA_PTR(result));
1511
1564
  }
1512
1565
  else{
@@ -1516,60 +1569,73 @@ FXIcon* FXRbCallIconMethod(const FXTableItem* recv,ID func){
1516
1569
 
1517
1570
  //----------------------------------------------------------------------
1518
1571
 
1519
- FXWindow* FXRbCallWindowMethod(const FXTableItem* recv,ID func,FXTable* table){
1572
+ FXWindow* FXRbCallWindowMethod_gvlcb(const FXTableItem* recv,const char *func,FXTable* table){
1520
1573
  VALUE obj=FXRbGetRubyObj(recv,false);
1521
1574
  FXASSERT(!NIL_P(obj));
1522
- VALUE result=rb_funcall(obj,func,1,to_ruby(table));
1575
+ VALUE result=rb_funcall(obj,rb_intern(func),1,to_ruby(table));
1576
+ FXRbUnregisterBorrowedRubyObj(table);
1523
1577
  return NIL_P(result) ? 0 : reinterpret_cast<FXWindow*>(DATA_PTR(result));
1524
1578
  }
1525
1579
 
1526
1580
  //----------------------------------------------------------------------
1527
1581
 
1528
1582
  // Call function with "FXRange" return value
1529
- FXRangef FXRbCallRangeMethod(FXObject* recv,ID func){
1583
+ FXRangef FXRbCallRangeMethod_gvlcb(FXObject* recv,const char *func){
1530
1584
  VALUE obj=FXRbGetRubyObj(recv,false);
1531
1585
  FXASSERT(!NIL_P(obj));
1532
- VALUE result=rb_funcall(obj,func,0,NULL);
1586
+ VALUE result=rb_funcall(obj,rb_intern(func),0,NULL);
1533
1587
  return *reinterpret_cast<FXRangef*>(DATA_PTR(result));
1534
1588
  }
1535
1589
 
1536
1590
  //----------------------------------------------------------------------
1537
1591
 
1538
1592
  // Call functions with FXString return value
1539
- FXString FXRbCallStringMethod(const FXObject* recv, ID func){
1593
+ FXString FXRbCallStringMethod_gvlcb(const FXObject* recv, const char *func){
1540
1594
  VALUE obj=FXRbGetRubyObj(recv,false);
1541
1595
  FXASSERT(!NIL_P(obj));
1542
- VALUE result=rb_funcall(obj,func,0,NULL);
1596
+ VALUE result=rb_funcall(obj,rb_intern(func),0,NULL);
1543
1597
  return FXString(StringValuePtr(result));
1544
1598
  }
1545
1599
 
1546
1600
  //----------------------------------------------------------------------
1547
1601
 
1548
1602
  // Call functions with const FXchar* return value
1549
- const FXchar* FXRbCallCStringMethod(const FXObject* recv, ID func, const FXchar* message, const FXchar* hint){
1603
+ const FXchar* FXRbCallCStringMethod_gvlcb(const FXObject* recv, const char *func, const FXchar* message, const FXchar* hint){
1550
1604
  VALUE obj=FXRbGetRubyObj(recv,false);
1551
1605
  FXASSERT(!NIL_P(obj));
1552
- VALUE result=rb_funcall(obj,func,2,to_ruby(message),to_ruby(hint));
1606
+ VALUE result=rb_funcall(obj,rb_intern(func),2,to_ruby(message),to_ruby(hint));
1553
1607
  return NIL_P(result) ? 0 : StringValuePtr(result);
1554
1608
  }
1555
1609
 
1556
1610
  // Call functions with const FXchar* return value
1557
- const FXchar* FXRbCallCStringMethod(const FXObject* recv, ID func, const FXchar* context, const FXchar* message, const FXchar* hint){
1611
+ const FXchar* FXRbCallCStringMethod_gvlcb(const FXObject* recv, const char *func, const FXchar* context, const FXchar* message, const FXchar* hint){
1558
1612
  VALUE obj=FXRbGetRubyObj(recv,false);
1559
1613
  FXASSERT(!NIL_P(obj));
1560
- VALUE result=rb_funcall(obj,func,3,to_ruby(context),to_ruby(message),to_ruby(hint));
1614
+ VALUE result=rb_funcall(obj,rb_intern(func),3,to_ruby(context),to_ruby(message),to_ruby(hint));
1561
1615
  return NIL_P(result) ? 0 : StringValuePtr(result);
1562
1616
  }
1563
1617
  //----------------------------------------------------------------------
1564
1618
 
1565
1619
  // Call functions with FXwchar return value
1566
- FXwchar FXRbCallWCharMethod(const FXObject* recv, ID func){
1620
+ FXwchar FXRbCallWCharMethod_gvlcb(const FXObject* recv, const char *func){
1567
1621
  VALUE obj=FXRbGetRubyObj(recv,false);
1568
1622
  FXASSERT(!NIL_P(obj));
1569
- VALUE result=rb_funcall(obj,func,0,NULL);
1623
+ VALUE result=rb_funcall(obj,rb_intern(func),0,NULL);
1570
1624
  return static_cast<FXwchar>(NUM2ULONG(result));
1571
1625
  }
1572
1626
 
1627
+ void FXRbCallSetDashes_gvlcb(FXDC* recv,const char *func,FXuint dashoffset,const FXchar *dashpattern,FXuint dashlength){
1628
+ rb_funcall(FXRbGetRubyObj(recv,false),rb_intern(func),2,to_ruby(dashoffset),FXRbMakeArray(dashpattern,dashlength));
1629
+ }
1630
+
1631
+ void FXRbCallDCDrawMethod_gvlcb(FXDC* recv, const char * func, FXint x,FXint y,const FXString& string){
1632
+ rb_funcall(FXRbGetRubyObj(recv,false),rb_intern(func),3,to_ruby(x),to_ruby(y),to_ruby(string)); \
1633
+ }
1634
+
1635
+ void FXRbCallDCDrawMethod_gvlcb(FXDC* recv, const char * func, FXint x,FXint y,const FXchar* string,FXuint length){
1636
+ rb_funcall(FXRbGetRubyObj(recv,false),rb_intern(func),3,to_ruby(x),to_ruby(y),to_ruby(string,length)); \
1637
+ }
1638
+
1573
1639
  //----------------------------------------------------------------------
1574
1640
 
1575
1641
  // Special destructors to handle order dependencies
@@ -1684,59 +1750,25 @@ void FXRbFoldingList::enumerateItems(FXFoldingItem* fm,FXFoldingItem* to,FXObjec
1684
1750
 
1685
1751
  static ID id_cmp;
1686
1752
 
1687
- // Sort function stand-in for FXComboBox
1688
- FXint FXRbComboBox::sortFunc(const FXListItem* a,const FXListItem* b){
1689
- VALUE itemA = FXRbGetRubyObj(const_cast<FXListItem*>(a), "FXListItem *");
1690
- VALUE itemB = FXRbGetRubyObj(const_cast<FXListItem*>(b), "FXListItem *");
1691
- VALUE result=rb_funcall(itemA,id_cmp,1,itemB);
1692
- return static_cast<FXint>(NUM2INT(result));
1693
- }
1694
-
1695
-
1696
- // Sort function stand-in for FXFoldingList
1697
- FXint FXRbFoldingList::sortFunc(const FXFoldingItem* a,const FXFoldingItem* b){
1698
- VALUE itemA = FXRbGetRubyObj(const_cast<FXFoldingItem*>(a), "FXFoldingItem *");
1699
- VALUE itemB = FXRbGetRubyObj(const_cast<FXFoldingItem*>(b), "FXFoldingItem *");
1700
- VALUE result=rb_funcall(itemA,id_cmp,1,itemB);
1701
- return static_cast<FXint>(NUM2INT(result));
1702
- }
1703
-
1704
-
1705
- // Sort function stand-in for FXIconList
1706
- FXint FXRbIconList::sortFunc(const FXIconItem* a,const FXIconItem* b){
1707
- VALUE itemA = FXRbGetRubyObj(const_cast<FXIconItem*>(a), "FXIconItem *");
1708
- VALUE itemB = FXRbGetRubyObj(const_cast<FXIconItem*>(b), "FXIconItem *");
1709
- VALUE result = rb_funcall(itemA,id_cmp,1,itemB);
1710
- return static_cast<FXint>(NUM2INT(result));
1711
- }
1712
-
1713
-
1714
- // Sort function stand-in for FXList
1715
- FXint FXRbList::sortFunc(const FXListItem* a,const FXListItem* b){
1716
- VALUE itemA = FXRbGetRubyObj(const_cast<FXListItem*>(a), "FXListItem *");
1717
- VALUE itemB = FXRbGetRubyObj(const_cast<FXListItem*>(b), "FXListItem *");
1718
- VALUE result=rb_funcall(itemA,id_cmp,1,itemB);
1719
- return static_cast<FXint>(NUM2INT(result));
1720
- }
1721
-
1722
-
1723
- // Sort function stand-in for FXListBox
1724
- FXint FXRbListBox::sortFunc(const FXListItem* a,const FXListItem* b){
1725
- VALUE itemA = FXRbGetRubyObj(const_cast<FXListItem*>(a), "FXListItem *");
1726
- VALUE itemB = FXRbGetRubyObj(const_cast<FXListItem*>(b), "FXListItem *");
1727
- VALUE result=rb_funcall(itemA,id_cmp,1,itemB);
1728
- return static_cast<FXint>(NUM2INT(result));
1729
- }
1730
-
1731
-
1732
- // Sort function stand-in for FXTreeList
1733
- FXint FXRbTreeList::sortFunc(const FXTreeItem* a,const FXTreeItem* b){
1734
- VALUE itemA = FXRbGetRubyObj(const_cast<FXTreeItem*>(a), "FXTreeItem *");
1735
- VALUE itemB = FXRbGetRubyObj(const_cast<FXTreeItem*>(b), "FXTreeItem *");
1736
- VALUE result=rb_funcall(itemA,id_cmp,1,itemB);
1737
- return static_cast<FXint>(NUM2INT(result));
1738
- }
1739
-
1753
+ #define SORTFUNC(list, item) \
1754
+ FXint list::sortFunc(const item* a,const item* b){ \
1755
+ return list##_sortFunc(a, b); \
1756
+ } \
1757
+ FXint list##_sortFunc_gvlcb(const item* a,const item* b){ \
1758
+ VALUE itemA = FXRbGetRubyObj(const_cast<item*>(a), #item " *"); \
1759
+ VALUE itemB = FXRbGetRubyObj(const_cast<item*>(b), #item " *"); \
1760
+ VALUE result=rb_funcall(itemA,id_cmp,1,itemB); \
1761
+ return static_cast<FXint>(NUM2INT(result)); \
1762
+ }
1763
+
1764
+ SORTFUNC( FXRbComboBox, FXListItem )
1765
+ SORTFUNC( FXRbFoldingList, FXFoldingItem )
1766
+ SORTFUNC( FXRbIconList, FXIconItem )
1767
+ SORTFUNC( FXRbList, FXListItem )
1768
+ SORTFUNC( FXRbListBox, FXListItem )
1769
+ SORTFUNC( FXRbTreeList, FXTreeItem )
1770
+
1771
+ #undef SORTFUNC
1740
1772
 
1741
1773
  // Feedback buffer sort routine stand-in for FXGLViewer
1742
1774
  FXbool FXRbGLViewer::sortProc(FXfloat*& buffer,FXint& used,FXint& size){