win 0.3.24 → 0.3.25

Sign up to get free protection for your applications and to get access to all the features.
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