win 0.3.24 → 0.3.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/win/time.rb ADDED
@@ -0,0 +1,140 @@
1
+ require 'win/library'
2
+
3
+ module Win
4
+
5
+ # Includes functions related to Time in Windows
6
+ # In general you will want to use this module with Win::National because
7
+ # it contains the various LOCALE and TIME constants.
8
+ #
9
+ # *NB*: Millisecond granularity may NOT be supported by a hardware platform.
10
+ # The caller of these functions should not rely on more than second granularity.
11
+ # In fact, granularity of all the GetTime... functions is about ~16msec on Windows.
12
+ # You'll need to mess with QueryPerformanceFrequency() and QueryPerformanceCounter()
13
+ # to get real msec granularity on MS Windows;
14
+ #
15
+ module Time
16
+ extend Win::Library
17
+ TIME_ZONE_ID_UNKNOWN = 0
18
+ TIME_ZONE_ID_STANDARD = 1
19
+ TIME_ZONE_ID_DAYLIGHT = 2
20
+
21
+
22
+ ##
23
+ # QueryPerformanceFrequency Function
24
+ # Retrieves the frequency of the high-resolution performance counter, if one exists.
25
+ # The frequency cannot change while the system is running.
26
+ #
27
+ # [*Syntax*] BOOL WINAPI QueryPerformanceFrequency( lpFrequency );
28
+ #
29
+ # lpFrequency <out>
30
+ # Type: LARGE_INTEGER*
31
+ # A pointer to a variable that receives the current performance-counter frequency,
32
+ # in counts per second. If the installed hardware does not support a high-resolution
33
+ # performance counter, this parameter can be zero.
34
+ #
35
+ # *Returns*:: Type: BOOL
36
+ # If the installed hardware supports a high-resolution performance counter, the return
37
+ # value is nonzero. If the function fails, the return value is zero. To get extended
38
+ # error information, call GetLastError. For example, if the installed hardware does
39
+ # not support a high-resolution performance counter, the function fails.
40
+ #
41
+ # ---
42
+ # <b>Enhanced (snake_case) API: returns high-resolution performance counter frequency
43
+ # or nil if no high-resolution performance counter is available</b>
44
+ #
45
+ # :call-seq:
46
+ # frequency = query_performance_frequency()
47
+ #
48
+ function :QueryPerformanceFrequency, [:pointer], :int8,
49
+ &->(api){
50
+ freq = FFI::MemoryPointer.new(:int64)
51
+ api.call(freq) == 0 ? nil : freq.get_int64(0) }
52
+
53
+ ##
54
+ # QueryPerformanceCounter Function
55
+ # Retrieves the current value of the high-resolution performance counter.
56
+ #
57
+ # [*Syntax*] BOOL WINAPI QueryPerformanceCounter( __out LARGE_INTEGER *lpPerformanceCount );
58
+ #
59
+ # lpPerformanceCount <out>
60
+ # Type: LARGE_INTEGER*
61
+ # A pointer to a variable that receives the current performance-counter value, in counts.
62
+ #
63
+ # *Returns*:: Type: BOOL
64
+ # If the function succeeds, the return value is nonzero.
65
+ # If the function fails, the return value is zero. To get extended error information,
66
+ # call GetLastError.
67
+ # ---
68
+ # *Remarks*:
69
+ # On a multiprocessor computer, it should not matter which processor is called. However,
70
+ # you can get different results on different processors due to bugs in the basic
71
+ # input/output system (BIOS) or the hardware abstraction layer (HAL). To specify
72
+ # processor affinity for a thread, use the SetThreadAffinityMask function.
73
+ # ---
74
+ # <b>Enhanced (snake_case) API: returns current performance counter value, in counts.
75
+ # Returns nil if function fails</b>
76
+ #
77
+ # :call-seq:
78
+ # counter = query_performance_counter()
79
+ #
80
+ function :QueryPerformanceCounter, [:pointer], :int8,
81
+ &->(api){
82
+ count = FFI::MemoryPointer.new(:int64)
83
+ api.call(count) == 0 ? nil : count.get_int64(0) }
84
+
85
+ # Untested
86
+
87
+ ##
88
+ function :CompareFileTime, 'PP', 'L'
89
+ ##
90
+ function :DosDateTimeToFileTime, 'IIP', :int8, boolean: true
91
+ ##
92
+ function :FileTimeToDosDateTime, 'PPP', :int8, boolean: true
93
+ ##
94
+ function :FileTimeToLocalFileTime, 'PP', :int8, boolean: true
95
+ ##
96
+ function :FileTimeToSystemTime, 'PP', :int8, boolean: true
97
+ ##
98
+ function :GetFileTime, 'LPPP', :int8, boolean: true
99
+ ##
100
+ # [out] Pointer to a SYSTEMTIME structure to receive the current local date and time.
101
+ function :GetLocalTime, 'P', :void
102
+ ##
103
+ # This function retrieves the current system date and time. The system time is expressed in UTC.
104
+ # [out] Pointer to a SYSTEMTIME structure to receive the current system date and time.
105
+ function :GetSystemTime, 'P', :void
106
+ ##
107
+ function :GetSystemTimeAdjustment, 'PPP', :int8, boolean: true
108
+ ##
109
+ function :GetSystemTimeAsFileTime, 'P', :void
110
+ ##
111
+ function :GetTickCount, [], :void
112
+ ##
113
+ function :GetTimeFormat, 'ILPPPI', 'I'
114
+ ##
115
+ function :GetTimeZoneInformation, 'P', 'L'
116
+ ##
117
+ function :LocalFileTimeToFileTime, 'PP', :int8, boolean: true
118
+ ##
119
+ function :SetFileTime, 'LPPP', :int8, boolean: true
120
+ ##
121
+ function :SetLocalTime, 'P', :int8, boolean: true
122
+ ##
123
+ function :SetSystemTime, 'P', :int8, boolean: true
124
+ ##
125
+ function :SetTimeZoneInformation, 'P', :int8, boolean: true
126
+ ##
127
+ function :SetSystemTimeAdjustment, 'LI', :int8, boolean: true
128
+ ##
129
+ function :SystemTimeToFileTime, 'PP', :int8, boolean: true
130
+ ##
131
+ function :SystemTimeToTzSpecificLocalTime, 'PPP', :int8, boolean: true
132
+
133
+ ##
134
+ try_function :GetSystemTimes, 'PPP', :int8, boolean: true
135
+ ##
136
+ try_function :TzSpecificLocalTimeToSystemTime, 'PPP', :int8, boolean: true
137
+
138
+
139
+ end
140
+ end
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), "spec_helper" )
1
+ require 'spec_helper'
2
2
  require 'extension'
3
3
 
4
4
  module WinTest
@@ -8,7 +8,7 @@ module WinTest
8
8
  it 'transforms CamelCase strings' do
9
9
  'GetCharWidth32'.snake_case.should == 'get_char_width_32'
10
10
  end
11
-
11
+
12
12
  it 'leaves snake_case strings intact' do
13
13
  'keybd_event'.snake_case.should == 'keybd_event'
14
14
  end
@@ -33,41 +33,5 @@ module WinTest
33
33
  'GetCharWidth32'.to_w.bytes.to_a[-2..-1].should == [0, 0]
34
34
  end
35
35
  end
36
-
37
- # context '#to_vkeys' do
38
- # it 'transforms number char into [equivalent key code]' do
39
- # ('0'..'9').each {|char| char.to_vkeys.should == char.unpack('C')}
40
- # end
41
- #
42
- # it 'transforms uppercase letters into [shift, equivalent key code]' do
43
- # ('A'..'Z').each {|char| char.to_vkeys.should == [0x10, *char.unpack('C')]}
44
- # # Win.const_get(:VK_SHIFT) = 0x10 Bad coupling
45
- # end
46
- #
47
- # it 'transforms lowercase letters into [(upcase) key code]' do
48
- # ('a'..'z').each {|char| char.to_vkeys.should == char.upcase.unpack('C')}
49
- # end
50
- #
51
- # it 'transforms space into [equivalent key code]' do
52
- # " ".to_vkeys.should == " ".unpack('C')
53
- # end
54
- #
55
- # it 'raises error if char is not implemented punctuation' do
56
- # ('!'..'/').each {|char| lambda {char.to_vkeys}.should raise_error CONVERSION_ERROR }
57
- # (':'..'@').each {|char| lambda {char.to_vkeys}.should raise_error CONVERSION_ERROR }
58
- # ('['..'`').each {|char| lambda {char.to_vkeys}.should raise_error CONVERSION_ERROR }
59
- # ('{'..'~').each {|char| lambda {char.to_vkeys}.should raise_error CONVERSION_ERROR }
60
- # end
61
- #
62
- # it 'raises error if char is non-printable or non-ascii' do
63
- # lambda {1.chr.to_vkeys}.should raise_error CONVERSION_ERROR
64
- # lambda {230.chr.to_vkeys}.should raise_error CONVERSION_ERROR
65
- # end
66
- #
67
- # it 'raises error if string is multi-char' do
68
- # lambda {'hello'.to_vkeys}.should raise_error CONVERSION_ERROR
69
- # lambda {'23'.to_vkeys}.should raise_error CONVERSION_ERROR
70
- # end
71
- # end
72
36
  end
73
37
  end
data/spec/spec_helper.rb CHANGED
@@ -1,11 +1,35 @@
1
- $LOAD_PATH.unshift(File.dirname(__FILE__))
2
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
- require 'spec'
4
- require 'spec/autorun'
1
+ require 'bundler'
2
+ Bundler.setup
3
+ Bundler.require :test
5
4
  require 'win/gui'
6
5
 
7
6
  $debug = false
8
7
 
8
+ # Global test methods
9
+ def cygwin?
10
+ @cygwin_flag ||= `ruby -v` =~ /cygwin/
11
+ end
12
+
13
+ def os
14
+ @os_flag ||= cygwin? ? `cmd /c ver` : `ver`
15
+ end
16
+
17
+ def os_2000?
18
+ os =~ /Version 5.0/
19
+ end
20
+
21
+ def os_xp?
22
+ os =~ /XP/
23
+ end
24
+
25
+ def os_vista?
26
+ os =~ /Version 6.0/
27
+ end
28
+
29
+ def os_7?
30
+ os =~ /Version 6.1/
31
+ end
32
+
9
33
  # Customize RSpec with my own extensions
10
34
  module ClassMacros
11
35
 
@@ -25,7 +49,7 @@ module ClassMacros
25
49
  file, line = args
26
50
  end
27
51
  File.open(file) do |f|
28
- f.lines.to_a[line.to_i-1].gsub( /(spec.*?{)|(use.*?{)|}/, '' ).strip
52
+ f.lines.to_a[line.to_i-1].gsub(/(spec.*?{)|(use.*?{)|}/, '').strip
29
53
  end
30
54
  end
31
55
  end
@@ -33,86 +57,51 @@ end
33
57
  # Customize RSpec with my own extensions
34
58
  module InstanceMacros
35
59
  def use
36
- lambda{yield}.should_not raise_error
60
+ lambda { yield }.should_not raise_error
37
61
  end
38
62
 
39
63
  def any_block
40
- lambda{|*args| args}
64
+ lambda { |*args| args }
41
65
  end
42
66
  end
43
67
 
44
- Spec::Runner.configure do |config|
68
+ RSpec.configure do |config|
45
69
  config.extend(ClassMacros)
46
70
  config.include(InstanceMacros)
47
-
48
- # class << Spec::ExampleGroup
49
- ## def spoc &block
50
- ## it description_from(caller[0]), &block
51
- ## end
52
- # end
53
71
  end
54
72
 
55
- # Global test methods
56
- def cygwin?
57
- @cygwin_flag ||= `ruby -v` =~ /cygwin/
58
- end
59
-
60
- def os
61
- @os_flag ||= cygwin? ? `cmd /c ver` : `ver`
62
- end
63
-
64
- def os_2000?
65
- os =~ /Version 5.0/
66
- end
67
-
68
- def os_xp?
69
- os =~ /XP/
73
+ KEY_DELAY = 0.001
74
+ IMPOSSIBLE = 'Impossible'
75
+ CONVERSION_ERROR = /Can.t convert/
76
+ SLEEP_DELAY = 0.02
77
+ APP_PATH = File.join(File.dirname(__FILE__), "../misc/locknote/LockNote.exe")
78
+ APP_START = cygwin? ? "cmd /c start `cygpath -w #{APP_PATH}`" : 'start "" "' + APP_PATH + '"'
79
+ WIN_TITLE = 'LockNote - Steganos LockNote'
80
+ WIN_RECT = [710, 400, 1210, 800]
81
+ WIN_CLASS = 'ATL:00434098'
82
+ STATUSBAR_CLASS = 'msctls_statusbar32'
83
+ TEXTAREA_CLASS = 'ATL:00434310'
84
+ DESKTOP_CLASS = '#32769'
85
+ MENU_CLASS = '#32768'
86
+
87
+ def any_handle
88
+ find_window(nil, nil)
70
89
  end
71
90
 
72
- def os_vista?
73
- os =~ /Version 6.0/
91
+ def not_a_handle
92
+ 123
74
93
  end
75
94
 
76
- def os_7?
77
- os =~ /Version 6.1/
95
+ def buffer
96
+ FFI::MemoryPointer.new(:char, 1024)
78
97
  end
79
98
 
80
- module WinTest
81
-
82
- KEY_DELAY = 0.001
83
- IMPOSSIBLE = 'Impossible'
84
- CONVERSION_ERROR = /Can.t convert/
85
- SLEEP_DELAY = 0.02
86
- APP_PATH = File.join(File.dirname(__FILE__), "../misc/locknote/LockNote.exe" )
87
- APP_START = cygwin? ? "cmd /c start `cygpath -w #{APP_PATH}`" : 'start "" "' + APP_PATH + '"'
88
- WIN_TITLE = 'LockNote - Steganos LockNote'
89
- WIN_RECT = [710, 400, 1210, 800]
90
- WIN_CLASS = 'ATL:00434098'
91
- STATUSBAR_CLASS = 'msctls_statusbar32'
92
- TEXTAREA_CLASS = 'ATL:00434310'
93
- DESKTOP_CLASS = '#32769'
94
- MENU_CLASS = '#32768'
95
-
96
- def any_handle
97
- find_window(nil, nil)
98
- end
99
-
100
- def not_a_handle
101
- 123
102
- end
103
-
104
- def buffer
105
- FFI::MemoryPointer.new(:char, 1024)
106
- end
107
-
108
- def pointer(type=:long, num=1)
109
- FFI::MemoryPointer.new(type, num)
110
- end
99
+ def pointer(type=:long, num=1)
100
+ FFI::MemoryPointer.new(type, num)
111
101
  end
112
102
 
113
103
  module WinTestApp
114
104
 
115
- include WinTest
116
105
  include Win::Gui
117
106
  #include Win::Gui::Convenience
118
107
 
@@ -120,15 +109,15 @@ module WinTestApp
120
109
  system APP_START
121
110
  sleep SLEEP_DELAY until (handle = find_window(nil, WIN_TITLE))
122
111
 
123
- textarea = find_window_ex(handle, 0, TEXTAREA_CLASS, nil)
124
- app = "Locknote" # App identifier
112
+ textarea = find_window_ex(handle, 0, TEXTAREA_CLASS, nil)
113
+ app = "Locknote" # App identifier
125
114
 
126
115
  eigen_class = class << app;
127
116
  self;
128
- end # Extracting app's eigenclass
129
- eigen_class.class_eval do # Defining singleton methods on app
130
- define_method(:handle) {handle}
131
- define_method(:textarea) {textarea}
117
+ end # Extracting app's eigenclass
118
+ eigen_class.class_eval do # Defining singleton methods on app
119
+ define_method(:handle) { handle }
120
+ define_method(:textarea) { textarea }
132
121
  end
133
122
 
134
123
  @launched_test_app = app
data/spec/win/dde_spec.rb CHANGED
@@ -1,529 +1,527 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'spec_helper'
2
2
  require 'win/dde'
3
3
 
4
- module WinDdeTest
5
- include WinTest
6
- include Win::Dde
7
- include Win::Gui::Message
4
+ include WinTest
5
+ include Win::Dde
6
+ include Win::Gui::Message
7
+
8
+ POKE_STRING = "Poke_string"
9
+
10
+ def dde_cmd
11
+ APPCLASS_STANDARD
12
+ end
13
+
14
+ def dde_callback
15
+ ->(*args){}
16
+ end
17
+
18
+ def zero_id
19
+ FFI::MemoryPointer.new(:long).write_long(0)
20
+ end
21
+
22
+ def buffer
23
+ FFI::MemoryPointer.new(:char, 1024)
24
+ end
25
+
26
+ def string_pointer
27
+ FFI::MemoryPointer.from_string("Pointer_string")
28
+ end
29
+
30
+ def extract_values(*args)
31
+ type, format, conv, hsz1, hsz2, data, data1, data2 = *args
32
+ @server_conv = conv
33
+ [Win::Dde::TYPES[type], format, conv,
34
+ dde_query_string(@client_id, hsz1),
35
+ dde_query_string(@client_id, hsz2),
36
+ data, data1, data2]
37
+ end
38
+
39
+ def setup_server(&server_block)
40
+ @client_calls = []
41
+ @server_calls = []
42
+ @client_id, st = dde_initialize(APPCLASS_STANDARD) { |*args| @client_calls << extract_values(*args); DDE_FACK }
43
+ @server_id, st = dde_initialize(APPCLASS_STANDARD,
44
+ &server_block || proc { |*args| @server_calls << extract_values(*args); DDE_FACK })
45
+ @service_handle = dde_create_string_handle(@server_id, 'service 2', CP_WINANSI)
46
+ @topic_handle = dde_create_string_handle(@server_id, 'topic 2', CP_WINANSI)
47
+ dde_name_service(@server_id, @service_handle, DNS_REGISTER)
48
+ end
49
+
50
+ def teardown_server
51
+ if @print
52
+ p @server_calls, @client_calls
53
+ p @server_conv
54
+ p ERRORS[dde_get_last_error(@server_id)]
55
+ p ERRORS[dde_get_last_error(@client_id)]
56
+ @print = nil
57
+ end
58
+ dde_name_service(@server_id, @service_handle, DNS_UNREGISTER) if @server_id && @service_handle
59
+ dde_free_string_handle(@server_id, @service_handle) if @server_id && @service_handle
60
+ dde_free_string_handle(@server_id, @topic_handle) if @server_id && @topic_handle
61
+ dde_uninitialize(@server_id) if @server_id
62
+ dde_uninitialize(@client_id) if @client_id
63
+ if @conv_handle
64
+ dde_disconnect(@conv_handle)
65
+ @conv_handle = nil
66
+ end
67
+ @data = nil
68
+ end
8
69
 
9
- POKE_STRING = "Poke_string"
70
+ describe Win::Dde, ' contains a set of pre-defined Windows API functions' do
10
71
 
11
- def dde_cmd
12
- APPCLASS_STANDARD
13
- end
72
+ describe '#register_clipboard_format' do
73
+ spec { use { RegisterClipboardFormat(format_name = "XlTable") } }
74
+ spec { use { register_clipboard_format(format_name = "XlTable") } }
14
75
 
15
- def dde_callback
16
- ->(*args){}
17
- end
76
+ it 'returns format id (int) if successfully registered format' do
77
+ id = register_clipboard_format("XlTable")
78
+ id.should_not == 0
79
+ id.should_not == nil
80
+ end
18
81
 
19
- def zero_id
20
- FFI::MemoryPointer.new(:long).write_long(0)
21
- end
82
+ it 'returns same format id for already registered format' do
83
+ id1 = register_clipboard_format("XlTable")
84
+ id2 = register_clipboard_format("XlTable")
85
+ id1.should == id2
86
+ end
22
87
 
23
- def buffer
24
- FFI::MemoryPointer.new(:char, 1024)
88
+ it 'returns nil if not able to register format' do
89
+ register_clipboard_format("").should == nil
90
+ end
25
91
  end
26
92
 
27
- def string_pointer
28
- FFI::MemoryPointer.from_string("Pointer_string")
29
- end
93
+ describe '#dde_initialize' do
94
+ after(:each) { dde_uninitialize(@id) if @id }
30
95
 
31
- def extract_values(*args)
32
- type, format, conv, hsz1, hsz2, data, data1, data2 = *args
33
- @server_conv = conv
34
- [Win::Dde::TYPES[type], format, conv,
35
- dde_query_string(@client_id, hsz1),
36
- dde_query_string(@client_id, hsz2),
37
- data, data1, data2]
38
- end
96
+ spec { use { status = DdeInitialize(id = zero_id, dde_callback, dde_cmd, unused=0); @id = id.read_long } }
97
+ spec { use { @id, status = dde_initialize(@id=0, dde_cmd, &dde_callback) } }
39
98
 
40
- def setup_server(&server_block)
41
- @client_calls = []
42
- @server_calls = []
43
- @client_id, st = dde_initialize(APPCLASS_STANDARD) {|*args| @client_calls << extract_values(*args); DDE_FACK}
44
- @server_id, st = dde_initialize(APPCLASS_STANDARD,
45
- &server_block || proc {|*args| @server_calls << extract_values(*args); DDE_FACK} )
46
- @service_handle = dde_create_string_handle(@server_id, 'service 2', CP_WINANSI)
47
- @topic_handle = dde_create_string_handle(@server_id, 'topic 2', CP_WINANSI)
48
- dde_name_service(@server_id, @service_handle, DNS_REGISTER)
49
- end
99
+ it 'with zero instance_id, returns integer id and DMLERR_NO_ERROR if initialization successful' do
100
+ @id, status = dde_initialize(0, APPCLASS_STANDARD) { |*args|}
101
+ @id.should be_an Integer
102
+ @id.should_not == 0
103
+ status.should == DMLERR_NO_ERROR
104
+ end
50
105
 
51
- def teardown_server
52
- if @print
53
- p @server_calls, @client_calls
54
- p @server_conv
55
- p ERRORS[dde_get_last_error(@server_id)]
56
- p ERRORS[dde_get_last_error(@client_id)]
57
- @print = nil
106
+ it 'with nil instance_id, returns integer id and DMLERR_NO_ERROR if initialization successful' do
107
+ @id, status = dde_initialize(nil, APPCLASS_STANDARD) { |*args|}
108
+ @id.should be_an Integer
109
+ @id.should_not == 0
110
+ status.should == DMLERR_NO_ERROR
58
111
  end
59
- dde_name_service(@server_id, @service_handle, DNS_UNREGISTER) if @server_id && @service_handle
60
- dde_free_string_handle(@server_id, @service_handle) if @server_id && @service_handle
61
- dde_free_string_handle(@server_id, @topic_handle) if @server_id && @topic_handle
62
- dde_uninitialize(@server_id) if @server_id
63
- dde_uninitialize(@client_id) if @client_id
64
- if @conv_handle
65
- dde_disconnect(@conv_handle)
66
- @conv_handle = nil
112
+
113
+ it 'with omitted instance_id, returns integer id and DMLERR_NO_ERROR if initialization successful' do
114
+ @id, status = dde_initialize(APPCLASS_STANDARD) { |*args|}
115
+ @id.should be_an Integer
116
+ @id.should_not == 0
117
+ status.should == DMLERR_NO_ERROR
67
118
  end
68
- @data = nil
69
- end
70
119
 
71
- describe Win::Dde, ' contains a set of pre-defined Windows API functions' do
120
+ it 'returns error status if initialization unsuccessful' do
121
+ @id, status = dde_initialize(12345, APPCLASS_STANDARD) { |*args|}
122
+ status.should == DMLERR_INVALIDPARAMETER
123
+ @id.should == nil
124
+ end
125
+
126
+ it 'is able to reinitialize with correct id' do
127
+ @id, status = dde_initialize(APPCLASS_STANDARD) { |*args|}
128
+ new_id, status = dde_initialize(@id, APPCLASS_STANDARD) { |*args|}
129
+ status.should == DMLERR_NO_ERROR
130
+ new_id.should == @id
131
+ end
132
+ end # describe 'dde_initialize'
72
133
 
73
- describe '#register_clipboard_format' do
74
- spec{ use{ RegisterClipboardFormat(format_name = "XlTable") }}
75
- spec{ use{ register_clipboard_format(format_name = "XlTable") }}
134
+ context 'after initialization:' do
135
+ before(:each) { @id, status = dde_initialize(APPCLASS_STANDARD) { |*args|} }
136
+ after(:each) { dde_uninitialize(@id) if @id }
76
137
 
77
- it 'returns format id (int) if successfully registered format' do
78
- id = register_clipboard_format("XlTable")
79
- id.should_not == 0
80
- id.should_not == nil
81
- end
138
+ describe '#dde_uninitialize' do
82
139
 
83
- it 'returns same format id for already registered format' do
84
- id1 = register_clipboard_format("XlTable")
85
- id2 = register_clipboard_format("XlTable")
86
- id1.should == id2
140
+ spec { use { status = DdeUninitialize(@id) } }
141
+ spec { use { id, status = dde_uninitialize(@id) } }
142
+
143
+ it 'returns true if uninitialization successful' do
144
+ res = dde_uninitialize(@id)
145
+ res.should == true
87
146
  end
88
147
 
89
- it 'returns nil if not able to register format' do
90
- register_clipboard_format("").should == nil
148
+ it 'returns false if initialization unsuccessful' do
149
+ res = dde_uninitialize(12345)
150
+ res.should == false
91
151
  end
92
- end
152
+ end # describe '#dde_uninitialize'
93
153
 
94
- describe '#dde_initialize' do
95
- after(:each) {dde_uninitialize(@id) if @id}
154
+ describe '#dde_create_string_handle' do
155
+ after(:each) { dde_free_string_handle(@id, @string_handle) if @string_handle }
96
156
 
97
- spec{ use{ status = DdeInitialize( id = zero_id, dde_callback, dde_cmd, unused=0); @id = id.read_long}}
98
- spec{ use{ @id, status = dde_initialize(@id=0, dde_cmd, &dde_callback) }}
157
+ spec { use { @string_handle = DdeCreateStringHandle(id=0, string_pointer, code_page_id=CP_WINANSI) } }
158
+ spec { use { @string_handle = dde_create_string_handle(id=0, string='Any String', code_page_id=CP_WINANSI) } }
99
159
 
100
- it 'with zero instance_id, returns integer id and DMLERR_NO_ERROR if initialization successful' do
101
- @id, status = dde_initialize(0, APPCLASS_STANDARD) {|*args| }
102
- @id.should be_an Integer
103
- @id.should_not == 0
104
- status.should == DMLERR_NO_ERROR
160
+ it 'returns nonzero Integer handle to a string (passable to other DDEML functions)' do
161
+ @string_handle = dde_create_string_handle(@id, 'My String', CP_WINANSI)
162
+ @string_handle.should be_an Integer
163
+ @string_handle.should_not == 0
105
164
  end
106
165
 
107
- it 'with nil instance_id, returns integer id and DMLERR_NO_ERROR if initialization successful' do
108
- @id, status = dde_initialize(nil, APPCLASS_STANDARD) {|*args| }
109
- @id.should be_an Integer
110
- @id.should_not == 0
111
- status.should == DMLERR_NO_ERROR
166
+ it 'creates handle even if code_page is omitted' do
167
+ @string_handle = dde_create_string_handle(@id, 'My String')
168
+ @string_handle.should be_an Integer
169
+ @string_handle.should_not == 0
112
170
  end
113
171
 
114
- it 'with omitted instance_id, returns integer id and DMLERR_NO_ERROR if initialization successful' do
115
- @id, status = dde_initialize(APPCLASS_STANDARD) {|*args| }
116
- @id.should be_an Integer
117
- @id.should_not == 0
118
- status.should == DMLERR_NO_ERROR
172
+ it 'creating two handles for the SAME string (inside one instance) USUALLY returns same handle' do
173
+ @string_handle = dde_create_string_handle(@id, 'My String')
174
+ 10.times do
175
+ string_handle1 = dde_create_string_handle(@id, 'My String')
176
+ string_handle1.should == @string_handle
177
+ dde_free_string_handle(@id, string_handle1)
178
+ end
119
179
  end
120
180
 
121
- it 'returns error status if initialization unsuccessful' do
122
- @id, status = dde_initialize(12345, APPCLASS_STANDARD) {|*args| }
123
- status.should == DMLERR_INVALIDPARAMETER
124
- @id.should == nil
181
+ it 'created different handles for two different strings ' do
182
+ @string_handle = dde_create_string_handle(@id, 'My String')
183
+ string_handle1 = dde_create_string_handle(@id, 'My String1')
184
+ string_handle1.should_not == @string_handle
185
+ dde_free_string_handle(@id, string_handle1)
125
186
  end
126
187
 
127
- it 'is able to reinitialize with correct id' do
128
- @id, status = dde_initialize(APPCLASS_STANDARD) {|*args| }
129
- new_id, status = dde_initialize(@id, APPCLASS_STANDARD) {|*args| }
130
- status.should == DMLERR_NO_ERROR
131
- new_id.should == @id
188
+ it 'returns nil if unable to register handle to a string' do
189
+ @string_handle = dde_create_string_handle(@id, "", CP_WINANSI)
190
+ @string_handle.should == nil
132
191
  end
133
- end # describe 'dde_initialize'
192
+ end # describe '#dde_create_string_handle'
134
193
 
135
- context 'after initialization:' do
136
- before(:each) {@id, status = dde_initialize(APPCLASS_STANDARD) {|*args| }}
137
- after(:each) {dde_uninitialize(@id) if @id}
194
+ context "with dde string handle to 'My String 2'" do
195
+ before(:each) { @string_handle = dde_create_string_handle(@id, 'My String 2', CP_WINANSI) }
196
+ after(:each) { dde_free_string_handle(@id, @string_handle) }
138
197
 
139
- describe '#dde_uninitialize' do
198
+ describe '#dde_query_string' do
140
199
 
141
- spec{ use{ status = DdeUninitialize( @id ) }}
142
- spec{ use{ id, status = dde_uninitialize( @id) }}
200
+ spec { use { string = DdeQueryString(@id, @string_handle, buffer, buffer.size, code_page=CP_WINANSI) } }
201
+ spec { use { string = dde_query_string(@id, @string_handle, code_page=CP_WINANSI) } }
143
202
 
144
- it 'returns true if uninitialization successful' do
145
- res = dde_uninitialize(@id)
146
- res.should == true
203
+ it 'retrieves string that given string handle refers to' do
204
+ num_chars = DdeQueryString(@id, @string_handle, buf = buffer, buf.size, CP_WINANSI)
205
+ num_chars.should == 11
206
+ buf.read_string.should == 'My String 2'
147
207
  end
148
208
 
149
- it 'returns false if initialization unsuccessful' do
150
- res = dde_uninitialize(12345)
151
- res.should == false
209
+ it 'retrieves string that given string handle refers to' do
210
+ string = dde_query_string(@id, @string_handle, CP_WINANSI)
211
+ string.should == 'My String 2'
152
212
  end
153
- end # describe '#dde_uninitialize'
154
-
155
- describe '#dde_create_string_handle' do
156
- after(:each) {dde_free_string_handle(@id, @string_handle) if @string_handle}
157
213
 
158
- spec{ use{ @string_handle = DdeCreateStringHandle(id=0, string_pointer, code_page_id=CP_WINANSI) }}
159
- spec{ use{ @string_handle = dde_create_string_handle(id=0, string='Any String', code_page_id=CP_WINANSI)}}
160
-
161
- it 'returns nonzero Integer handle to a string (passable to other DDEML functions)' do
162
- @string_handle = dde_create_string_handle(@id, 'My String', CP_WINANSI)
163
- @string_handle.should be_an Integer
164
- @string_handle.should_not == 0
214
+ it 'retrieves string even if code_page is omitted' do
215
+ string = dde_query_string(@id, @string_handle)
216
+ string.should == 'My String 2'
165
217
  end
166
218
 
167
- it 'creates handle even if code_page is omitted' do
168
- @string_handle = dde_create_string_handle(@id, 'My String')
169
- @string_handle.should be_an Integer
170
- @string_handle.should_not == 0
219
+ it 'returns nil attempting to retrieve invalid handle' do
220
+ string = dde_query_string(@id, 12345)
221
+ string.should == nil
171
222
  end
223
+ end # describe '#dde_query_string'
172
224
 
173
- it 'creating two handles for the SAME string (inside one instance) USUALLY returns same handle' do
174
- @string_handle = dde_create_string_handle(@id, 'My String')
175
- 10.times do
176
- string_handle1 = dde_create_string_handle(@id, 'My String')
177
- string_handle1.should == @string_handle
178
- dde_free_string_handle(@id, string_handle1)
179
- end
180
- end
225
+ describe '#dde_free_string_handle' do
181
226
 
182
- it 'created different handles for two different strings ' do
183
- @string_handle = dde_create_string_handle(@id, 'My String')
184
- string_handle1 = dde_create_string_handle(@id, 'My String1')
185
- string_handle1.should_not == @string_handle
186
- dde_free_string_handle(@id, string_handle1)
187
- end
227
+ spec { use { success = DdeFreeStringHandle(@id, @string_handle) } }
228
+ spec { use { success = dde_free_string_handle(@id, @string_handle) } }
188
229
 
189
- it 'returns nil if unable to register handle to a string' do
190
- @string_handle = dde_create_string_handle(@id, "", CP_WINANSI)
191
- @string_handle.should == nil
230
+ it 'returns true when freeing string handle registered with DDEML' do
231
+ res = dde_free_string_handle(@id, @string_handle)
232
+ res.should == true
192
233
  end
193
- end # describe '#dde_create_string_handle'
194
-
195
- context "with dde string handle to 'My String 2'" do
196
- before(:each) {@string_handle = dde_create_string_handle(@id, 'My String 2', CP_WINANSI)}
197
- after(:each) {dde_free_string_handle(@id, @string_handle)}
198
-
199
- describe '#dde_query_string' do
200
-
201
- spec{ use{ string = DdeQueryString(@id, @string_handle, buffer, buffer.size, code_page=CP_WINANSI)}}
202
- spec{ use{ string = dde_query_string(@id, @string_handle, code_page=CP_WINANSI )}}
203
-
204
- it 'retrieves string that given string handle refers to' do
205
- num_chars = DdeQueryString(@id, @string_handle, buf = buffer, buf.size, CP_WINANSI)
206
- num_chars.should == 11
207
- buf.read_string.should == 'My String 2'
208
- end
209
-
210
- it 'retrieves string that given string handle refers to' do
211
- string = dde_query_string(@id, @string_handle, CP_WINANSI)
212
- string.should == 'My String 2'
213
- end
214
-
215
- it 'retrieves string even if code_page is omitted' do
216
- string = dde_query_string(@id, @string_handle)
217
- string.should == 'My String 2'
218
- end
219
-
220
- it 'returns nil attempting to retrieve invalid handle' do
221
- string = dde_query_string(@id, 12345)
222
- string.should == nil
223
- end
224
- end # describe '#dde_query_string'
225
-
226
- describe '#dde_free_string_handle' do
227
-
228
- spec{ use{ success = DdeFreeStringHandle( @id, @string_handle)}}
229
- spec{ use{ success = dde_free_string_handle( @id, @string_handle )}}
230
-
231
- it 'returns true when freeing string handle registered with DDEML' do
232
- res = dde_free_string_handle(@id, @string_handle)
233
- res.should == true
234
- end
235
-
236
- it 'returns false attempting to free unregistered handle' do
237
- res = dde_free_string_handle(@id, 12345)
238
- res.should == false
239
- end
240
-
241
- it 'keeps string accessible while references to it still exist' do
242
- # creates second handle to 'My String 2'
243
- string_handle_1 = dde_create_string_handle(@id, 'My String 2', CP_WINANSI)
244
-
245
- dde_free_string_handle(@id, @string_handle)
246
- dde_query_string(@id, @string_handle).should == 'My String 2'
247
-
248
- dde_free_string_handle(@id, string_handle_1)
249
- dde_query_string(@id, @string_handle).should == nil
250
- end
251
-
252
- it 'makes string inaccessible once its last handle is freed' do
253
- dde_free_string_handle(@id, @string_handle)
254
- dde_query_string(@id, @string_handle).should == nil
255
- end
256
- end # describe '#dde_free_string_handle'
257
-
258
- describe '#dde_get_last_error' do
259
- spec{ use{ error_code = DdeGetLastError(@id) }}
260
- spec{ use{ error_code = dde_get_last_error(@id) }}
261
-
262
- it 'original API returns DMLERR_NO_ERROR if there is no last DDE error for given app instance' do
263
- DdeGetLastError(@id).should == DMLERR_NO_ERROR
264
- end
265
-
266
- it 'snake_case API returns nil if there is no last DDE error for given app instance' do
267
- dde_get_last_error(@id).should == nil
268
- end
269
-
270
- it 'returns error code of last DDE error for given app instance' do
271
- dde_name_service(@id, 1234, DNS_REGISTER )
272
- dde_get_last_error(@id).should == DMLERR_INVALIDPARAMETER
273
- end
274
- end # describe '#dde_get_last_error'
275
-
276
- end # context "with dde string handle to 'My String'"
277
- end # context 'after initialization:'
278
-
279
- context 'with synthetic DDE client/server' do
280
- before(:each){ setup_server }
281
- after(:each) { teardown_server}
282
-
283
- describe '#dde_name_service' do
284
- spec{ use{ success = dde_name_service(@server_id, @service_handle, cmd=DNS_UNREGISTER ) }}
285
- spec{ use{ success = DdeNameService(@server_id, @service_handle, reserved=0, cmd=DNS_UNREGISTER) }}
286
-
287
- it 'registers or unregisters the service names that DDE server supports' do
288
- pending 'Register/Unregister messages don`t show up in @server_calls :('
289
- success = dde_name_service(@server_id, @service_handle, DNS_REGISTER )
290
- success.should == true
291
- success = dde_name_service(@server_id, @service_handle, DNS_UNREGISTER )
292
- success.should == true
234
+
235
+ it 'returns false attempting to free unregistered handle' do
236
+ res = dde_free_string_handle(@id, 12345)
237
+ res.should == false
293
238
  end
294
- end # describe '#dde_name_service'
295
-
296
- describe '#dde_connect' do
297
- spec{ use{ @conv_handle = DdeConnect( instance_id=0, service=0, topic=0, context=nil) }}
298
- spec{ use{ @conv_handle = dde_connect( instance_id=0, service=0, topic=0, context=nil) }}
299
-
300
- it 'connects to existing DDE server (self in this case)' do
301
- @conv_handle = dde_connect( @server_id, @service_handle, @topic_handle, context=nil)
302
-
303
- @server_calls.first[0].should == 'XTYP_CONNECT'
304
- @server_calls.first[3].should == 'topic 2'
305
- @server_calls.first[4].should == 'service 2'
306
- @server_calls[1][0].should == 'XTYP_CONNECT_CONFIRM'
307
- @server_calls[1][3].should == 'topic 2'
308
- @server_calls[1][4].should == 'service 2'
309
- dde_disconnect(@server_conv).should == true
310
- dde_disconnect(@conv_handle).should == true
239
+
240
+ it 'keeps string accessible while references to it still exist' do
241
+ # creates second handle to 'My String 2'
242
+ string_handle_1 = dde_create_string_handle(@id, 'My String 2', CP_WINANSI)
243
+
244
+ dde_free_string_handle(@id, @string_handle)
245
+ dde_query_string(@id, @string_handle).should == 'My String 2'
246
+
247
+ dde_free_string_handle(@id, string_handle_1)
248
+ dde_query_string(@id, @string_handle).should == nil
311
249
  end
312
250
 
313
- it 'connects to existing DDE server (from @client, NOT self)' do
314
- pending 'something is wrong when connecting to separate service instance, uninitialize fails'
315
- @conv_handle = dde_connect( @client_id, @service_handle, @topic_handle, context=nil)
316
- puts @conv_handle
251
+ it 'makes string inaccessible once its last handle is freed' do
252
+ dde_free_string_handle(@id, @string_handle)
253
+ dde_query_string(@id, @string_handle).should == nil
317
254
  end
318
- end # describe '#dde_connect'
255
+ end # describe '#dde_free_string_handle'
319
256
 
320
- describe '#dde_disconnect' do
321
- spec{ use{ success = DdeDisconnect(conversation_handle=0) }}
322
- spec{ use{ success = dde_disconnect(conversation_handle=0) }}
257
+ describe '#dde_get_last_error' do
258
+ spec { use { error_code = DdeGetLastError(@id) } }
259
+ spec { use { error_code = dde_get_last_error(@id) } }
323
260
 
324
- it 'fails to disconnect if not valid conversation handle given' do
325
- dde_disconnect(12345).should == false
261
+ it 'original API returns DMLERR_NO_ERROR if there is no last DDE error for given app instance' do
262
+ DdeGetLastError(@id).should == DMLERR_NO_ERROR
326
263
  end
327
264
 
328
- it 'disconnects from existing (self) DDE server' do
329
- conv_handle = dde_connect( @server_id, @service_handle, @topic_handle, context=nil)
330
- dde_disconnect(conv_handle).should == true
265
+ it 'snake_case API returns nil if there is no last DDE error for given app instance' do
266
+ dde_get_last_error(@id).should == nil
331
267
  end
332
268
 
333
- it 'disconnects from existing (self) DDE server' do
334
- pending 'XTYP_DISCONNECT is not received by server callback (since we are disconnecting from self?)'
335
- conv_handle = dde_connect( @server_id, @service_handle, @topic_handle, context=nil)
336
- dde_disconnect(conv_handle).should == true
337
- @server_calls.last[0].should == "XTYP_DISCONNECT"
338
- p @server_calls, @client_calls, @server_conv
339
- p ERRORS[dde_get_last_error(@server_id)]
340
- p ERRORS[dde_get_last_error(@client_id)]
269
+ it 'returns error code of last DDE error for given app instance' do
270
+ dde_name_service(@id, 1234, DNS_REGISTER)
271
+ dde_get_last_error(@id).should == DMLERR_INVALIDPARAMETER
341
272
  end
342
- end # describe '#dde_disconnect'
343
- end # context 'with synthetic DDE server'
344
-
345
- describe "#dde_client_transaction" do
346
- before(:each) do
347
- setup_server do |*args|
348
- @server_calls << extract_values(*args)
349
- @data_out, size = dde_get_data(args[5]) if args.first == XTYP_POKE || args.first == XTYP_EXECUTE
350
- DDE_FACK
351
- end
352
- @conv_handle = dde_connect( @server_id, @service_handle, @topic_handle, context=nil)
353
- @data_in = FFI::MemoryPointer.from_string POKE_STRING
354
- end
355
- after(:each) { teardown_server}
273
+ end # describe '#dde_get_last_error'
356
274
 
357
- spec{ use{ DdeClientTransaction(data=nil, size=0, conv=0, item=0, format=0, type=0, timeout=0, result=nil) }}
358
- spec{ use{ dde_client_transaction(data=nil, size=0, conv=0, item=0, format=0, type=0, timeout=0, result=nil) }}
275
+ end # context "with dde string handle to 'My String'"
276
+ end # context 'after initialization:'
359
277
 
278
+ context 'with synthetic DDE client/server' do
279
+ before(:each) { setup_server }
280
+ after(:each) { teardown_server }
360
281
 
361
- it "returns 0/nil if initiated transaction unsuccessful" do
362
- res = DdeClientTransaction(@data_in, @data_in.size, 1234, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
363
- res.should == 0 # wrong conversation handle
364
- res = dde_client_transaction(@data_in, @data_in.size, 1234, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
365
- res.should == nil # wrong conversation handle
366
- res = dde_client_transaction(@data_in, @data_in.size, @conv_handle, 0, CF_TEXT, XTYP_POKE, 1000, nil)
367
- res.should == nil # wrong item handle (cannot be NULL in XTYP_POKE transaction)
368
- @server_calls.any? {|call| call[0] == 'XTYP_POKE'}.should be_false
369
- end
282
+ describe '#dde_name_service' do
283
+ spec { use { success = dde_name_service(@server_id, @service_handle, cmd=DNS_UNREGISTER) } }
284
+ spec { use { success = DdeNameService(@server_id, @service_handle, reserved=0, cmd=DNS_UNREGISTER) } }
370
285
 
371
- it "original api is used by CLIENT to begins a data transaction with server" do
372
- res = DdeClientTransaction(@data_in, @data_in.size, @conv_handle, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
373
- res.should == 1
374
- @server_calls.any? {|call| call[0] == 'XTYP_POKE'}.should be_true
375
- @data_out.read_string.should == POKE_STRING.rstrip
286
+ it 'registers or unregisters the service names that DDE server supports' do
287
+ pending 'Register/Unregister messages don`t show up in @server_calls :('
288
+ success = dde_name_service(@server_id, @service_handle, DNS_REGISTER)
289
+ success.should == true
290
+ success = dde_name_service(@server_id, @service_handle, DNS_UNREGISTER)
291
+ success.should == true
292
+ end
293
+ end # describe '#dde_name_service'
294
+
295
+ describe '#dde_connect' do
296
+ spec { use { @conv_handle = DdeConnect(instance_id=0, service=0, topic=0, context=nil) } }
297
+ spec { use { @conv_handle = dde_connect(instance_id=0, service=0, topic=0, context=nil) } }
298
+
299
+ it 'connects to existing DDE server (self in this case)' do
300
+ @conv_handle = dde_connect(@server_id, @service_handle, @topic_handle, context=nil)
301
+
302
+ @server_calls.first[0].should == 'XTYP_CONNECT'
303
+ @server_calls.first[3].should == 'topic 2'
304
+ @server_calls.first[4].should == 'service 2'
305
+ @server_calls[1][0].should == 'XTYP_CONNECT_CONFIRM'
306
+ @server_calls[1][3].should == 'topic 2'
307
+ @server_calls[1][4].should == 'service 2'
308
+ dde_disconnect(@server_conv).should == true
309
+ dde_disconnect(@conv_handle).should == true
376
310
  end
377
311
 
378
- it "snake_case api begins a data transaction between a client and a server" do
379
- res = dde_client_transaction(@data_in, @data_in.size, @conv_handle, 0, 0, XTYP_EXECUTE, 1000, nil)
380
- res.should be_true
381
- @server_calls.any? {|call| call[0] == 'XTYP_EXECUTE'}.should be_true
382
- @data_out.read_string.should == POKE_STRING.rstrip
312
+ it 'connects to existing DDE server (from @client, NOT self)' do
313
+ pending 'something is wrong when connecting to separate service instance, uninitialize fails'
314
+ @conv_handle = dde_connect(@client_id, @service_handle, @topic_handle, context=nil)
315
+ puts @conv_handle
383
316
  end
384
- end # describe dde_client_transaction
317
+ end # describe '#dde_connect'
385
318
 
386
- describe '#dde_get_data' do
387
- after(:each) { teardown_server}
319
+ describe '#dde_disconnect' do
320
+ spec { use { success = DdeDisconnect(conversation_handle=0) } }
321
+ spec { use { success = dde_disconnect(conversation_handle=0) } }
388
322
 
389
- spec{ use{ data_pointer, size = dde_get_data( data_handle = 123, max = 1073741823, offset = 0) }}
390
- spec{ use{ size = DdeGetData( data_handle = 123, nil, 0, 0) }} # returns dde data set size in bytes
391
- spec{ use{ size = DdeGetData( data_handle = 123, FFI::MemoryPointer.new(:char, 1024), max = 1024, offset = 0) }}
323
+ it 'fails to disconnect if not valid conversation handle given' do
324
+ dde_disconnect(12345).should == false
325
+ end
392
326
 
393
- it 'original API returns 0 if trying to address invalid dde data handle' do
394
- DdeGetData( data_handle = 123, nil, 0, 0).should == 0
327
+ it 'disconnects from existing (self) DDE server' do
328
+ conv_handle = dde_connect(@server_id, @service_handle, @topic_handle, context=nil)
329
+ dde_disconnect(conv_handle).should == true
395
330
  end
396
331
 
397
- it 'snake_case API returns [nil, 0] if trying to address invalid dde data handle' do
398
- data, size = dde_get_data( data_handle = 123, 3741823, 0)
399
- data.should == nil
332
+ it 'disconnects from existing (self) DDE server' do
333
+ pending 'XTYP_DISCONNECT is not received by server callback (since we are disconnecting from self?)'
334
+ conv_handle = dde_connect(@server_id, @service_handle, @topic_handle, context=nil)
335
+ dde_disconnect(conv_handle).should == true
336
+ @server_calls.last[0].should == "XTYP_DISCONNECT"
337
+ p @server_calls, @client_calls, @server_conv
338
+ p ERRORS[dde_get_last_error(@server_id)]
339
+ p ERRORS[dde_get_last_error(@client_id)]
400
340
  end
341
+ end # describe '#dde_disconnect'
342
+ end # context 'with synthetic DDE server'
343
+
344
+ describe "#dde_client_transaction" do
345
+ before(:each) do
346
+ setup_server do |*args|
347
+ @server_calls << extract_values(*args)
348
+ @data_out, size = dde_get_data(args[5]) if args.first == XTYP_POKE || args.first == XTYP_EXECUTE
349
+ DDE_FACK
350
+ end
351
+ @conv_handle = dde_connect(@server_id, @service_handle, @topic_handle, context=nil)
352
+ @data_in = FFI::MemoryPointer.from_string POKE_STRING
353
+ end
354
+ after(:each) { teardown_server }
355
+
356
+ spec { use { DdeClientTransaction(data=nil, size=0, conv=0, item=0, format=0, type=0, timeout=0, result=nil) } }
357
+ spec { use { dde_client_transaction(data=nil, size=0, conv=0, item=0, format=0, type=0, timeout=0, result=nil) } }
358
+
401
359
 
402
- it 'returns dde data if used inside dde callback block' do
403
- setup_server do |*args|
404
- @server_calls << extract_values(*args);
405
- if args[0] == XTYP_POKE
406
- data_handle = args[5]
407
- data, size = dde_get_data(data_handle)
408
- data.should be_an FFI::MemoryPointer
409
- data.read_string.should == POKE_STRING.rstrip
410
- size.should == 12
411
- DdeGetData(data_handle, nil, 0, 0).should == 12
412
- data = FFI::MemoryPointer.new(:char, 1024)
413
- DdeGetData(data_handle, data, data.size, 0).should == 12
414
- data.read_string.should == POKE_STRING.rstrip
415
- end
416
- DDE_FACK
360
+ it "returns 0/nil if initiated transaction unsuccessful" do
361
+ res = DdeClientTransaction(@data_in, @data_in.size, 1234, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
362
+ res.should == 0 # wrong conversation handle
363
+ res = dde_client_transaction(@data_in, @data_in.size, 1234, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
364
+ res.should == nil # wrong conversation handle
365
+ res = dde_client_transaction(@data_in, @data_in.size, @conv_handle, 0, CF_TEXT, XTYP_POKE, 1000, nil)
366
+ res.should == nil # wrong item handle (cannot be NULL in XTYP_POKE transaction)
367
+ @server_calls.any? { |call| call[0] == 'XTYP_POKE' }.should be_false
368
+ end
369
+
370
+ it "original api is used by CLIENT to begins a data transaction with server" do
371
+ res = DdeClientTransaction(@data_in, @data_in.size, @conv_handle, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
372
+ res.should == 1
373
+ @server_calls.any? { |call| call[0] == 'XTYP_POKE' }.should be_true
374
+ @data_out.read_string.should == POKE_STRING.rstrip
375
+ end
376
+
377
+ it "snake_case api begins a data transaction between a client and a server" do
378
+ res = dde_client_transaction(@data_in, @data_in.size, @conv_handle, 0, 0, XTYP_EXECUTE, 1000, nil)
379
+ res.should be_true
380
+ @server_calls.any? { |call| call[0] == 'XTYP_EXECUTE' }.should be_true
381
+ @data_out.read_string.should == POKE_STRING.rstrip
382
+ end
383
+ end # describe dde_client_transaction
384
+
385
+ describe '#dde_get_data' do
386
+ after(:each) { teardown_server }
387
+
388
+ spec { use { data_pointer, size = dde_get_data(data_handle = 123, max = 1073741823, offset = 0) } }
389
+ spec { use { size = DdeGetData(data_handle = 123, nil, 0, 0) } } # returns dde data set size in bytes
390
+ spec { use { size = DdeGetData(data_handle = 123, FFI::MemoryPointer.new(:char, 1024), max = 1024, offset = 0) } }
391
+
392
+ it 'original API returns 0 if trying to address invalid dde data handle' do
393
+ DdeGetData(data_handle = 123, nil, 0, 0).should == 0
394
+ end
395
+
396
+ it 'snake_case API returns [nil, 0] if trying to address invalid dde data handle' do
397
+ data, size = dde_get_data(data_handle = 123, 3741823, 0)
398
+ data.should == nil
399
+ end
400
+
401
+ it 'returns dde data if used inside dde callback block' do
402
+ setup_server do |*args|
403
+ @server_calls << extract_values(*args);
404
+ if args[0] == XTYP_POKE
405
+ data_handle = args[5]
406
+ data, size = dde_get_data(data_handle)
407
+ data.should be_an FFI::MemoryPointer
408
+ data.read_string.should == POKE_STRING.rstrip
409
+ size.should == 12
410
+ DdeGetData(data_handle, nil, 0, 0).should == 12
411
+ data = FFI::MemoryPointer.new(:char, 1024)
412
+ DdeGetData(data_handle, data, data.size, 0).should == 12
413
+ data.read_string.should == POKE_STRING.rstrip
417
414
  end
418
- @conv_handle = dde_connect( @server_id, @service_handle, @topic_handle, context=nil)
419
- str = FFI::MemoryPointer.from_string POKE_STRING
420
- dde_client_transaction(str, str.size, @conv_handle, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
415
+ DDE_FACK
421
416
  end
417
+ @conv_handle = dde_connect(@server_id, @service_handle, @topic_handle, context=nil)
418
+ str = FFI::MemoryPointer.from_string POKE_STRING
419
+ dde_client_transaction(str, str.size, @conv_handle, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
420
+ end
422
421
 
423
- it 'dde data handle expires once transaction is finished (DDE_FACK)' do
424
- setup_server do |*args|
425
- @server_calls << extract_values(*args);
426
- DDE_FACK
427
- end
428
- @conv_handle = dde_connect( @server_id, @service_handle, @topic_handle, context=nil)
429
- str = FFI::MemoryPointer.from_string POKE_STRING
430
- dde_client_transaction(str, str.size, @conv_handle, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
431
-
432
- # only inside callback block dde data handle is valid (while transaction still in progress)
433
- data, size = dde_get_data(@server_calls.last[5])
434
- data.should == nil
435
- size.should == 0
422
+ it 'dde data handle expires once transaction is finished (DDE_FACK)' do
423
+ setup_server do |*args|
424
+ @server_calls << extract_values(*args);
425
+ DDE_FACK
436
426
  end
427
+ @conv_handle = dde_connect(@server_id, @service_handle, @topic_handle, context=nil)
428
+ str = FFI::MemoryPointer.from_string POKE_STRING
429
+ dde_client_transaction(str, str.size, @conv_handle, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
430
+
431
+ # only inside callback block dde data handle is valid (while transaction still in progress)
432
+ data, size = dde_get_data(@server_calls.last[5])
433
+ data.should == nil
434
+ size.should == 0
435
+ end
437
436
 
438
- end # describe '#dde_get_data'
439
-
440
- describe "#dde_access_data" do
441
- after(:each) { teardown_server}
442
-
443
- spec{ use{ success = DdeAccessData(data_handle = 123, data_size=zero_id) }}
444
- spec{ use{ data_pointer, size = dde_access_data(data_handle = 123) }}
445
-
446
- it "provides access to the data in the specified DDE data handle (both inside and outside of callback)" do
447
- setup_server do |*args|
448
- @server_calls << extract_values(*args)
449
- if args[0] == XTYP_POKE
450
- data_handle = args[5]
451
- data, size = dde_access_data(data_handle)
452
- data.should be_kind_of FFI::Pointer
453
- data.read_string.should == POKE_STRING.rstrip
454
- size.should == 12
455
- buf = FFI::MemoryPointer.new(:int16)
456
- data = DdeAccessData(data_handle, buf)
457
- buf.get_int16(0).should == 12
458
- data.should be_kind_of FFI::Pointer
459
- data.read_string.should == POKE_STRING.rstrip
460
- dde_unaccess_data(data_handle)
461
- end
462
- DDE_FACK
437
+ end # describe '#dde_get_data'
438
+
439
+ describe "#dde_access_data" do
440
+ after(:each) { teardown_server }
441
+
442
+ spec { use { success = DdeAccessData(data_handle = 123, data_size=zero_id) } }
443
+ spec { use { data_pointer, size = dde_access_data(data_handle = 123) } }
444
+
445
+ it "provides access to the data in the specified DDE data handle (both inside and outside of callback)" do
446
+ setup_server do |*args|
447
+ @server_calls << extract_values(*args)
448
+ if args[0] == XTYP_POKE
449
+ data_handle = args[5]
450
+ data, size = dde_access_data(data_handle)
451
+ data.should be_kind_of FFI::Pointer
452
+ data.read_string.should == POKE_STRING.rstrip
453
+ size.should == 12
454
+ buf = FFI::MemoryPointer.new(:int16)
455
+ data = DdeAccessData(data_handle, buf)
456
+ buf.get_int16(0).should == 12
457
+ data.should be_kind_of FFI::Pointer
458
+ data.read_string.should == POKE_STRING.rstrip
459
+ dde_unaccess_data(data_handle)
463
460
  end
464
- @conv_handle = dde_connect( @server_id, @service_handle, @topic_handle, context=nil)
465
- str = FFI::MemoryPointer.from_string POKE_STRING
466
- dde_client_transaction(str, str.size, @conv_handle, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
461
+ DDE_FACK
467
462
  end
463
+ @conv_handle = dde_connect(@server_id, @service_handle, @topic_handle, context=nil)
464
+ str = FFI::MemoryPointer.from_string POKE_STRING
465
+ dde_client_transaction(str, str.size, @conv_handle, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
466
+ end
468
467
 
469
- it 'dde data handle expires once transaction is finished (DDE_FACK)' do
470
- setup_server do |*args|
471
- @server_calls << extract_values(*args);
472
- DDE_FACK
473
- end
474
- @conv_handle = dde_connect( @server_id, @service_handle, @topic_handle, context=nil)
475
- str = FFI::MemoryPointer.from_string POKE_STRING
476
- dde_client_transaction(str, str.size, @conv_handle, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
477
-
478
- # only inside callback block dde data handle is valid (while transaction still in progress)
479
- data, size = dde_access_data(@server_calls.last[5])
480
- data.should == nil
481
- size.should == 0
468
+ it 'dde data handle expires once transaction is finished (DDE_FACK)' do
469
+ setup_server do |*args|
470
+ @server_calls << extract_values(*args);
471
+ DDE_FACK
482
472
  end
483
- end # describe dde_access_data
473
+ @conv_handle = dde_connect(@server_id, @service_handle, @topic_handle, context=nil)
474
+ str = FFI::MemoryPointer.from_string POKE_STRING
475
+ dde_client_transaction(str, str.size, @conv_handle, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
476
+
477
+ # only inside callback block dde data handle is valid (while transaction still in progress)
478
+ data, size = dde_access_data(@server_calls.last[5])
479
+ data.should == nil
480
+ size.should == 0
481
+ end
482
+ end # describe dde_access_data
484
483
 
485
- describe "#dde_unaccess_data" do
486
- spec{ use{ success = DdeUnaccessData(data_handle = 123) }}
487
- spec{ use{ success = dde_unaccess_data(data_handle = 123) }}
484
+ describe "#dde_unaccess_data" do
485
+ spec { use { success = DdeUnaccessData(data_handle = 123) } }
486
+ spec { use { success = dde_unaccess_data(data_handle = 123) } }
488
487
 
489
- it "returns 0/false if given invalid DDE data handle " do
490
- DdeUnaccessData(data_handle = 123).should == 0
491
- dde_unaccess_data(data_handle = 123).should == false
492
- end
488
+ it "returns 0/false if given invalid DDE data handle " do
489
+ DdeUnaccessData(data_handle = 123).should == 0
490
+ dde_unaccess_data(data_handle = 123).should == false
491
+ end
493
492
 
494
- it "unaccesses a DDE data handle that was previously accessed" do
495
- setup_server do |*args|
496
- @server_calls << extract_values(*args);
497
- if args[0] == XTYP_POKE
498
- data_handle = args[5]
499
- dde_unaccess_data(data_handle).should == true
493
+ it "unaccesses a DDE data handle that was previously accessed" do
494
+ setup_server do |*args|
495
+ @server_calls << extract_values(*args);
496
+ if args[0] == XTYP_POKE
497
+ data_handle = args[5]
498
+ dde_unaccess_data(data_handle).should == true
500
499
 
501
- data, size = dde_access_data(data_handle)
502
- data.should be_kind_of FFI::Pointer
503
- data.read_string.should == POKE_STRING.rstrip
500
+ data, size = dde_access_data(data_handle)
501
+ data.should be_kind_of FFI::Pointer
502
+ data.read_string.should == POKE_STRING.rstrip
504
503
 
505
- dde_unaccess_data(data_handle).should == true
506
- end
507
- DDE_FACK
504
+ dde_unaccess_data(data_handle).should == true
508
505
  end
509
- @conv_handle = dde_connect( @server_id, @service_handle, @topic_handle, context=nil)
510
- str = FFI::MemoryPointer.from_string POKE_STRING
511
- dde_client_transaction(str, str.size, @conv_handle, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
506
+ DDE_FACK
512
507
  end
508
+ @conv_handle = dde_connect(@server_id, @service_handle, @topic_handle, context=nil)
509
+ str = FFI::MemoryPointer.from_string POKE_STRING
510
+ dde_client_transaction(str, str.size, @conv_handle, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
511
+ end
513
512
 
514
- it 'dde data handle expires once transaction is finished (DDE_FACK)' do
515
- setup_server do |*args|
516
- @server_calls << extract_values(*args);
517
- DDE_FACK
518
- end
519
- @conv_handle = dde_connect( @server_id, @service_handle, @topic_handle, context=nil)
520
- str = FFI::MemoryPointer.from_string POKE_STRING
521
- dde_client_transaction(str, str.size, @conv_handle, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
522
-
523
- # only inside callback block dde data handle is valid (while transaction still in progress)
524
- dde_unaccess_data(@server_calls.last[5]).should == false
513
+ it 'dde data handle expires once transaction is finished (DDE_FACK)' do
514
+ setup_server do |*args|
515
+ @server_calls << extract_values(*args);
516
+ DDE_FACK
525
517
  end
518
+ @conv_handle = dde_connect(@server_id, @service_handle, @topic_handle, context=nil)
519
+ str = FFI::MemoryPointer.from_string POKE_STRING
520
+ dde_client_transaction(str, str.size, @conv_handle, @topic_handle, CF_TEXT, XTYP_POKE, 1000, nil)
526
521
 
527
- end # describe dde_unaccess_data
528
- end
529
- end
522
+ # only inside callback block dde data handle is valid (while transaction still in progress)
523
+ dde_unaccess_data(@server_calls.last[5]).should == false
524
+ end
525
+
526
+ end # describe dde_unaccess_data
527
+ end