rb-scpt 1.0.1 → 1.0.2

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/bin/rb-scpt-1.0.1.gem +0 -0
  3. data/extconf.rb +12 -12
  4. data/rb-scpt.gemspec +10 -10
  5. data/sample/AB_export_vcard.rb +16 -16
  6. data/sample/AB_list_people_with_emails.rb +4 -4
  7. data/sample/Add_iCal_event.rb +12 -12
  8. data/sample/Create_daily_iCal_todos.rb +28 -28
  9. data/sample/Export_Address_Book_phone_numbers.rb +52 -52
  10. data/sample/Hello_world.rb +10 -10
  11. data/sample/List_iTunes_playlist_names.rb +3 -3
  12. data/sample/Make_Mail_message.rb +24 -24
  13. data/sample/Open_file_in_TextEdit.rb +5 -5
  14. data/sample/Organize_Mail_messages.rb +46 -46
  15. data/sample/Print_folder_tree.rb +5 -5
  16. data/sample/Select_all_HTML_files.rb +6 -6
  17. data/sample/Set_iChat_status.rb +12 -12
  18. data/sample/Simple_Finder_GUI_Scripting.rb +6 -6
  19. data/sample/Stagger_Finder_windows.rb +9 -9
  20. data/sample/TextEdit_demo.rb +71 -71
  21. data/sample/iTunes_top40_to_html.rb +28 -30
  22. data/src/SendThreadSafe.c +293 -293
  23. data/src/SendThreadSafe.h +108 -108
  24. data/src/lib/_aem/aemreference.rb +997 -998
  25. data/src/lib/_aem/codecs.rb +609 -610
  26. data/src/lib/_aem/connect.rb +197 -197
  27. data/src/lib/_aem/encodingsupport.rb +67 -67
  28. data/src/lib/_aem/findapp.rb +75 -75
  29. data/src/lib/_aem/mactypes.rb +241 -242
  30. data/src/lib/_aem/send.rb +268 -268
  31. data/src/lib/_aem/typewrappers.rb +52 -52
  32. data/src/lib/_appscript/defaultterminology.rb +266 -266
  33. data/src/lib/_appscript/referencerenderer.rb +230 -233
  34. data/src/lib/_appscript/reservedkeywords.rb +106 -106
  35. data/src/lib/_appscript/safeobject.rb +125 -125
  36. data/src/lib/_appscript/terminology.rb +448 -449
  37. data/src/lib/aem.rb +238 -238
  38. data/src/lib/kae.rb +1487 -1487
  39. data/src/lib/osax.rb +647 -647
  40. data/src/lib/rb-scpt.rb +1065 -1065
  41. data/src/rbae.c +595 -595
  42. data/test/test_aemreference.rb +104 -107
  43. data/test/test_appscriptcommands.rb +131 -134
  44. data/test/test_appscriptreference.rb +96 -99
  45. data/test/test_codecs.rb +166 -168
  46. data/test/test_findapp.rb +13 -16
  47. data/test/test_mactypes.rb +70 -72
  48. data/test/test_osax.rb +46 -48
  49. data/test/testall.sh +4 -4
  50. metadata +8 -7
@@ -6,274 +6,274 @@
6
6
 
7
7
  module Send
8
8
 
9
- # Defines the Event class, which represents an Apple event that's packed and ready to send,
10
- # and the EventError class, which contains error information for a failed event.
9
+ # Defines the Event class, which represents an Apple event that's packed and ready to send,
10
+ # and the EventError class, which contains error information for a failed event.
11
11
 
12
- require "ae"
13
- require "kae"
14
- require "_aem/codecs"
15
-
16
- class Event
17
- # Represents an Apple event.
18
-
19
- # Clients don't instantiate this class directly; instead, new instances are returned by AEM::Application#event.
20
-
21
- attr_reader :AEM_event
22
-
23
- def initialize(address, event_code, params={}, atts={}, transaction=KAE::KAnyTransactionID,
24
- return_id= KAE::KAutoGenerateReturnID, codecs=DefaultCodecs)
25
- # Create and pack a new Apple event ready for sending.
26
- # address : AEAddressDesc -- the target application, identified by PSN, URL, etc.
27
- # event_code : string -- 8-letter code indicating event's class and id, e.g. 'coregetd'
28
- # params : hash -- a hash of form {AE_code=>anything,...} containing zero or more event parameters (message arguments)
29
- # atts : hash -- a hash of form {AE_code=>anything,...} containing zero or more event attributes (event info)
30
- # transaction : integer -- transaction number; AEM::Application takes care of this value
31
- # return_id : integer -- reply event's ID
32
- # codecs : Codecs -- clients can provide custom Codecs object for packing parameters and unpacking result of this event
33
- @_event_code = event_code
34
- @_codecs = codecs
35
- @AEM_event = _create_apple_event(event_code[0, 4], event_code[-4, 4], address, return_id, transaction)
36
- atts.each {|key, value| @AEM_event.put_attr(key, codecs.pack(value))}
37
- params.each {|key, value| @AEM_event.put_param(key, codecs.pack(value))}
38
- end
39
-
40
- def _create_apple_event(event_class, event_id, target, return_id, transaction_id)
41
- # Hook method; may be overridden to customise how AppleEvent descriptors are created.
42
- return AE::AEDesc.new_apple_event(event_class, event_id, target, return_id, transaction_id)
43
- end
44
-
45
- def _send_apple_event(flags, timeout)
46
- # Hook method; may be overridden to customise how events are sent.
47
- return @AEM_event.send_thread_safe(flags, timeout)
48
- end
49
-
50
- def inspect
51
- return "#<AEM::Event @code=#{@_event_code}>"
52
- end
53
-
54
- alias_method :to_s, :inspect
55
-
56
- def send(timeout=KAE::KAEDefaultTimeout, flags=KAE::KAECanSwitchLayer + KAE::KAEWaitReply)
57
- # Send this Apple event (may be called any number of times).
58
- # timeout : int | KAEDefaultTimeout | KNoTimeOut -- number of ticks to wait for target process to reply before raising timeout error
59
- # flags : integer -- bitwise flags [1] indicating how target process should handle event
60
- # Result : anything -- value returned by application, if any
61
- #
62
- # [1] Should be the sum of zero or more of the following kae module constants:
63
- #
64
- # KAENoReply | KAEQueueReply | KAEWaitReply
65
- # KAEDontReconnect
66
- # KAEWantReceipt
67
- # KAENeverInteract | KAECanInteract | KAEAlwaysInteract
68
- # KAECanSwitchLayer
12
+ require "ae"
13
+ require "kae"
14
+ require "_aem/codecs"
69
15
 
70
- begin
71
- reply_event = _send_apple_event(flags, timeout)
72
- rescue AE::MacOSError => err # The Apple Event Manager raised an error.
73
- if not(@_event_code == 'aevtquit' and err.to_i == -609) # Ignore invalid connection errors (-609) when quitting
74
- raise EventError.new(err.to_i)
75
- end
76
- else # Decode application's reply, if any. May be a return value, error number (and optional message), or nothing.
77
- if reply_event.type != KAE::TypeNull
78
- event_result = {}
79
- reply_event.length.times do |i|
80
- key, value = reply_event.get_item(i + 1, KAE::TypeWildCard)
81
- event_result[key] = value
82
- end
83
- if event_result.has_key?(KAE::KeyErrorNumber) # The application raised an error.
84
- # Error info is unpacked using default codecs for reliability.
85
- e_num = DefaultCodecs.unpack(event_result[KAE::KeyErrorNumber])
86
- if e_num != 0 # Some apps (e.g. Finder) may return error code 0 to indicate a successful operation, so ignore this.
87
- raise EventError.new(e_num, event_result)
88
- end
89
- end
90
- if event_result.has_key?(KAE::KeyAEResult)
91
- # Return values are unpacked using [optionally] client-supplied codecs.
92
- # This allows aem clients such as appscript to customise how values are unpacked
93
- # (e.g. to unpack object specifier descs as appscript references instead of aem references).
94
- return @_codecs.unpack(event_result[KAE::KeyAEResult])
95
- end
96
- end
97
- end
98
- end
99
- end
100
-
101
-
102
- class EventError < RuntimeError
103
- # Represents an error raised by the Apple Event Manager or target application when a command fails.
104
- #
105
- # Methods:
106
- # number : integer -- MacOS error number
107
- # message : string -- application error message if any, or default error description if available
108
-
109
- # Most applications don't provide error description strings, so define default descriptions for the common ones.
110
- # Following default error descriptions are cribbed from the AppleScript Language Guide/MacErrors.h:
111
-
112
- MacOSErrorDescriptions = {
113
- # OS errors
114
- -34 => "Disk is full.",
115
- -35 => "Disk wasn't found.",
116
- -37 => "Bad name for file.",
117
- -38 => "File wasn't open.",
118
- -39 => "End of file error.",
119
- -42 => "Too many files open.",
120
- -43 => "File wasn't found.",
121
- -44 => "Disk is write protected.",
122
- -45 => "File is locked.",
123
- -46 => "Disk is locked.",
124
- -47 => "File is busy.",
125
- -48 => "Duplicate file name.",
126
- -49 => "File is already open.",
127
- -50 => "Parameter error.",
128
- -51 => "File reference number error.",
129
- -61 => "File not open with write permission.",
130
- -108 => "Out of memory.",
131
- -120 => "Folder wasn't found.",
132
- -124 => "Disk is disconnected.",
133
- -128 => "User canceled.",
134
- -192 => "A resource wasn't found.",
135
- -600 => "Application isn't running.",
136
- -601 => "Not enough room to launch application with special requirements.",
137
- -602 => "Application is not 32-bit clean.",
138
- -605 => "More memory is needed than is specified in the size resource.",
139
- -606 => "Application is background-only.",
140
- -607 => "Buffer is too small.",
141
- -608 => "No outstanding high-level event.",
142
- -609 => "Connection is invalid.",
143
- -904 => "Not enough system memory to connect to remote application.",
144
- -905 => "Remote access is not allowed.",
145
- -906 => "Application isn't running or program linking isn't enabled.",
146
- -915 => "Can't find remote machine.",
147
- -30720 => "Invalid date and time.",
148
- # AE errors
149
- -1700 => "Can't make some data into the expected type.",
150
- -1701 => "Some parameter is missing for command.",
151
- -1702 => "Some data could not be read.",
152
- -1703 => "Some data was the wrong type.",
153
- -1704 => "Some parameter was invalid.",
154
- -1705 => "Operation involving a list item failed.",
155
- -1706 => "Need a newer version of the Apple Event Manager.",
156
- -1707 => "Event isn't an Apple event.",
157
- -1708 => "Application could not handle this command.",
158
- -1709 => "AEResetTimer was passed an invalid reply.",
159
- -1710 => "Invalid sending mode was passed.",
160
- -1711 => "User canceled out of wait loop for reply or receipt.",
161
- -1712 => "Apple event timed out.",
162
- -1713 => "No user interaction allowed.",
163
- -1714 => "Wrong keyword for a special function.",
164
- -1715 => "Some parameter wasn't understood.",
165
- -1716 => "Unknown Apple event address type.",
166
- -1717 => "The handler is not defined.",
167
- -1718 => "Reply has not yet arrived.",
168
- -1719 => "Can't get reference. Invalid index.",
169
- -1720 => "Invalid range.",
170
- -1721 => "Wrong number of parameters for command.",
171
- -1723 => "Can't get reference. Access not allowed.",
172
- -1725 => "Illegal logical operator called.",
173
- -1726 => "Illegal comparison or logical.",
174
- -1727 => "Expected a reference.",
175
- -1728 => "Can't get reference.",
176
- -1729 => "Object counting procedure returned a negative count.",
177
- -1730 => "Container specified was an empty list.",
178
- -1731 => "Unknown object type.",
179
- -1739 => "Attempting to perform an invalid operation on a null descriptor.",
180
- # Application scripting errors
181
- -10000 => "Apple event handler failed.",
182
- -10001 => "Type error.",
183
- -10002 => "Invalid key form.",
184
- -10003 => "Can't set reference to given value. Access not allowed.",
185
- -10004 => "A privilege violation occurred.",
186
- -10005 => "The read operation wasn't allowed.",
187
- -10006 => "Can't set reference to given value.",
188
- -10007 => "The index of the event is too large to be valid.",
189
- -10008 => "The specified object is a property, not an element.",
190
- -10009 => "Can't supply the requested descriptor type for the data.",
191
- -10010 => "The Apple event handler can't handle objects of this class.",
192
- -10011 => "Couldn't handle this command because it wasn't part of the current transaction.",
193
- -10012 => "The transaction to which this command belonged isn't a valid transaction.",
194
- -10013 => "There is no user selection.",
195
- -10014 => "Handler only handles single objects.",
196
- -10015 => "Can't undo the previous Apple event or user action.",
197
- -10023 => "Enumerated value is not allowed for this property.",
198
- -10024 => "Class can't be an element of container.",
199
- -10025 => "Illegal combination of properties settings.",
200
- }
201
-
202
- # Following Cocoa Scripting error descriptions taken from:
203
- # http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/Classes/NSScriptCommand.html
204
- # http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/Classes/NSScriptObjectSpecifier.html
205
-
206
- CocoaErrorDescriptions = [
207
- ["NSReceiverEvaluationScriptError", "The object or objects specified by the direct parameter to a command could not be found."],
208
- ["NSKeySpecifierEvaluationScriptError", "The object or objects specified by a key (for commands that support key specifiers) could not be found."],
209
- ["NSArgumentEvaluationScriptError", "The object specified by an argument could not be found."],
210
- ["NSReceiversCantHandleCommandScriptError", "The receivers don't support the command sent to them."],
211
- ["NSRequiredArgumentsMissingScriptError", "An argument (or more than one argument) is missing."],
212
- ["NSArgumentsWrongScriptError", "An argument (or more than one argument) is of the wrong type or is otherwise invalid."],
213
- ["NSUnknownKeyScriptError", "An unidentified error occurred; indicates an error in the scripting support of the application."],
214
- ["NSInternalScriptError", "An unidentified internal error occurred; indicates an error in the scripting support of the application."],
215
- ["NSOperationNotSupportedForKeyScriptError", "The implementation of a scripting command signaled an error."],
216
- ["NSCannotCreateScriptCommandError", "Could not create the script command; an invalid or unrecognized Apple event was received."],
217
- ["NSNoSpecifierError", "No error encountered."],
218
- ["NSNoTopLevelContainersSpecifierError", "Someone called evaluate with nil."],
219
- ["NSContainerSpecifierError", "Error evaluating container specifier."],
220
- ["NSUnknownKeySpecifierError", "Receivers do not understand the key."],
221
- ["NSInvalidIndexSpecifierError", "Index out of bounds."],
222
- ["NSInternalSpecifierError", "Other internal error."],
223
- ["NSOperationNotSupportedForKeySpecifierError", "Attempt made to perform an unsupported operation on some key."]
224
- ]
225
-
226
- attr_reader :number, :raw
227
- alias_method :to_i, :number
228
-
229
- def initialize(number, reply_params={})
230
- @number = number
231
- @message = nil
232
- @raw = reply_params
233
- end
234
-
235
- def message
236
- if not @message
237
- desc = @raw[KAE::KeyErrorString]
238
- @message = DefaultCodecs.unpack(desc) if desc
239
- if @message.is_a?(String) and @number > 0
240
- # add clarification to default Cocoa Scripting error messages
241
- CocoaErrorDescriptions.each do |name, description|
242
- if @message[0, name.length] == name
243
- @message += " (#{description})"
244
- break
245
- end
246
- end
247
- end
248
- # if no message supplied or is a MacOSError, use default message if one is available
249
- @message = MacOSErrorDescriptions.fetch(number, '') if @message == nil
250
- end
251
- return @message
252
- end
253
-
254
- def to_s
255
- if message != ''
256
- return "EventError\n\t\tOSERROR: #{number}\n\t\tMESSAGE: #{message}"
257
- else
258
- return "EventError\n\t\tOSERROR: #{number}"
259
- end
260
- end
261
-
262
- # extended error info (some apps may return additional error info, though most don't)
263
-
264
- def offending_object
265
- desc = @raw[KAE::KOSAErrorOffendingObject]
266
- return desc ? DefaultCodecs.unpack(desc) : nil
267
- end
268
-
269
- def expected_type
270
- desc = @raw[KAE::KOSAErrorExpectedType]
271
- return desc ? DefaultCodecs.unpack(desc) : nil
272
- end
273
-
274
- def partial_result
275
- desc = @raw[KAE::KOSAErrorPartialResult]
276
- return desc ? DefaultCodecs.unpack(desc) : nil
277
- end
278
- end
16
+ class Event
17
+ # Represents an Apple event.
18
+
19
+ # Clients don't instantiate this class directly; instead, new instances are returned by AEM::Application#event.
20
+
21
+ attr_reader :AEM_event
22
+
23
+ def initialize(address, event_code, params={}, atts={}, transaction=KAE::KAnyTransactionID,
24
+ return_id= KAE::KAutoGenerateReturnID, codecs=DefaultCodecs)
25
+ # Create and pack a new Apple event ready for sending.
26
+ # address : AEAddressDesc -- the target application, identified by PSN, URL, etc.
27
+ # event_code : string -- 8-letter code indicating event's class and id, e.g. 'coregetd'
28
+ # params : hash -- a hash of form {AE_code=>anything,...} containing zero or more event parameters (message arguments)
29
+ # atts : hash -- a hash of form {AE_code=>anything,...} containing zero or more event attributes (event info)
30
+ # transaction : integer -- transaction number; AEM::Application takes care of this value
31
+ # return_id : integer -- reply event's ID
32
+ # codecs : Codecs -- clients can provide custom Codecs object for packing parameters and unpacking result of this event
33
+ @_event_code = event_code
34
+ @_codecs = codecs
35
+ @AEM_event = _create_apple_event(event_code[0, 4], event_code[-4, 4], address, return_id, transaction)
36
+ atts.each {|key, value| @AEM_event.put_attr(key, codecs.pack(value))}
37
+ params.each {|key, value| @AEM_event.put_param(key, codecs.pack(value))}
38
+ end
39
+
40
+ def _create_apple_event(event_class, event_id, target, return_id, transaction_id)
41
+ # Hook method; may be overridden to customise how AppleEvent descriptors are created.
42
+ return AE::AEDesc.new_apple_event(event_class, event_id, target, return_id, transaction_id)
43
+ end
44
+
45
+ def _send_apple_event(flags, timeout)
46
+ # Hook method; may be overridden to customise how events are sent.
47
+ return @AEM_event.send_thread_safe(flags, timeout)
48
+ end
49
+
50
+ def inspect
51
+ return "#<AEM::Event @code=#{@_event_code}>"
52
+ end
53
+
54
+ alias_method :to_s, :inspect
55
+
56
+ def send(timeout=KAE::KAEDefaultTimeout, flags=KAE::KAECanSwitchLayer + KAE::KAEWaitReply)
57
+ # Send this Apple event (may be called any number of times).
58
+ # timeout : int | KAEDefaultTimeout | KNoTimeOut -- number of ticks to wait for target process to reply before raising timeout error
59
+ # flags : integer -- bitwise flags [1] indicating how target process should handle event
60
+ # Result : anything -- value returned by application, if any
61
+ #
62
+ # [1] Should be the sum of zero or more of the following kae module constants:
63
+ #
64
+ # KAENoReply | KAEQueueReply | KAEWaitReply
65
+ # KAEDontReconnect
66
+ # KAEWantReceipt
67
+ # KAENeverInteract | KAECanInteract | KAEAlwaysInteract
68
+ # KAECanSwitchLayer
69
+
70
+ begin
71
+ reply_event = _send_apple_event(flags, timeout)
72
+ rescue AE::MacOSError => err # The Apple Event Manager raised an error.
73
+ if not(@_event_code == 'aevtquit' and err.to_i == -609) # Ignore invalid connection errors (-609) when quitting
74
+ raise EventError.new(err.to_i)
75
+ end
76
+ else # Decode application's reply, if any. May be a return value, error number (and optional message), or nothing.
77
+ if reply_event.type != KAE::TypeNull
78
+ event_result = {}
79
+ reply_event.length.times do |i|
80
+ key, value = reply_event.get_item(i + 1, KAE::TypeWildCard)
81
+ event_result[key] = value
82
+ end
83
+ if event_result.has_key?(KAE::KeyErrorNumber) # The application raised an error.
84
+ # Error info is unpacked using default codecs for reliability.
85
+ e_num = DefaultCodecs.unpack(event_result[KAE::KeyErrorNumber])
86
+ if e_num != 0 # Some apps (e.g. Finder) may return error code 0 to indicate a successful operation, so ignore this.
87
+ raise EventError.new(e_num, event_result)
88
+ end
89
+ end
90
+ if event_result.has_key?(KAE::KeyAEResult)
91
+ # Return values are unpacked using [optionally] client-supplied codecs.
92
+ # This allows aem clients such as appscript to customise how values are unpacked
93
+ # (e.g. to unpack object specifier descs as appscript references instead of aem references).
94
+ return @_codecs.unpack(event_result[KAE::KeyAEResult])
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+
102
+ class EventError < RuntimeError
103
+ # Represents an error raised by the Apple Event Manager or target application when a command fails.
104
+ #
105
+ # Methods:
106
+ # number : integer -- MacOS error number
107
+ # message : string -- application error message if any, or default error description if available
108
+
109
+ # Most applications don't provide error description strings, so define default descriptions for the common ones.
110
+ # Following default error descriptions are cribbed from the AppleScript Language Guide/MacErrors.h:
111
+
112
+ MacOSErrorDescriptions = {
113
+ # OS errors
114
+ -34 => "Disk is full.",
115
+ -35 => "Disk wasn't found.",
116
+ -37 => "Bad name for file.",
117
+ -38 => "File wasn't open.",
118
+ -39 => "End of file error.",
119
+ -42 => "Too many files open.",
120
+ -43 => "File wasn't found.",
121
+ -44 => "Disk is write protected.",
122
+ -45 => "File is locked.",
123
+ -46 => "Disk is locked.",
124
+ -47 => "File is busy.",
125
+ -48 => "Duplicate file name.",
126
+ -49 => "File is already open.",
127
+ -50 => "Parameter error.",
128
+ -51 => "File reference number error.",
129
+ -61 => "File not open with write permission.",
130
+ -108 => "Out of memory.",
131
+ -120 => "Folder wasn't found.",
132
+ -124 => "Disk is disconnected.",
133
+ -128 => "User canceled.",
134
+ -192 => "A resource wasn't found.",
135
+ -600 => "Application isn't running.",
136
+ -601 => "Not enough room to launch application with special requirements.",
137
+ -602 => "Application is not 32-bit clean.",
138
+ -605 => "More memory is needed than is specified in the size resource.",
139
+ -606 => "Application is background-only.",
140
+ -607 => "Buffer is too small.",
141
+ -608 => "No outstanding high-level event.",
142
+ -609 => "Connection is invalid.",
143
+ -904 => "Not enough system memory to connect to remote application.",
144
+ -905 => "Remote access is not allowed.",
145
+ -906 => "Application isn't running or program linking isn't enabled.",
146
+ -915 => "Can't find remote machine.",
147
+ -30720 => "Invalid date and time.",
148
+ # AE errors
149
+ -1700 => "Can't make some data into the expected type.",
150
+ -1701 => "Some parameter is missing for command.",
151
+ -1702 => "Some data could not be read.",
152
+ -1703 => "Some data was the wrong type.",
153
+ -1704 => "Some parameter was invalid.",
154
+ -1705 => "Operation involving a list item failed.",
155
+ -1706 => "Need a newer version of the Apple Event Manager.",
156
+ -1707 => "Event isn't an Apple event.",
157
+ -1708 => "Application could not handle this command.",
158
+ -1709 => "AEResetTimer was passed an invalid reply.",
159
+ -1710 => "Invalid sending mode was passed.",
160
+ -1711 => "User canceled out of wait loop for reply or receipt.",
161
+ -1712 => "Apple event timed out.",
162
+ -1713 => "No user interaction allowed.",
163
+ -1714 => "Wrong keyword for a special function.",
164
+ -1715 => "Some parameter wasn't understood.",
165
+ -1716 => "Unknown Apple event address type.",
166
+ -1717 => "The handler is not defined.",
167
+ -1718 => "Reply has not yet arrived.",
168
+ -1719 => "Can't get reference. Invalid index.",
169
+ -1720 => "Invalid range.",
170
+ -1721 => "Wrong number of parameters for command.",
171
+ -1723 => "Can't get reference. Access not allowed.",
172
+ -1725 => "Illegal logical operator called.",
173
+ -1726 => "Illegal comparison or logical.",
174
+ -1727 => "Expected a reference.",
175
+ -1728 => "Can't get reference.",
176
+ -1729 => "Object counting procedure returned a negative count.",
177
+ -1730 => "Container specified was an empty list.",
178
+ -1731 => "Unknown object type.",
179
+ -1739 => "Attempting to perform an invalid operation on a null descriptor.",
180
+ # Application scripting errors
181
+ -10000 => "Apple event handler failed.",
182
+ -10001 => "Type error.",
183
+ -10002 => "Invalid key form.",
184
+ -10003 => "Can't set reference to given value. Access not allowed.",
185
+ -10004 => "A privilege violation occurred.",
186
+ -10005 => "The read operation wasn't allowed.",
187
+ -10006 => "Can't set reference to given value.",
188
+ -10007 => "The index of the event is too large to be valid.",
189
+ -10008 => "The specified object is a property, not an element.",
190
+ -10009 => "Can't supply the requested descriptor type for the data.",
191
+ -10010 => "The Apple event handler can't handle objects of this class.",
192
+ -10011 => "Couldn't handle this command because it wasn't part of the current transaction.",
193
+ -10012 => "The transaction to which this command belonged isn't a valid transaction.",
194
+ -10013 => "There is no user selection.",
195
+ -10014 => "Handler only handles single objects.",
196
+ -10015 => "Can't undo the previous Apple event or user action.",
197
+ -10023 => "Enumerated value is not allowed for this property.",
198
+ -10024 => "Class can't be an element of container.",
199
+ -10025 => "Illegal combination of properties settings.",
200
+ }
201
+
202
+ # Following Cocoa Scripting error descriptions taken from:
203
+ # http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/Classes/NSScriptCommand.html
204
+ # http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/Classes/NSScriptObjectSpecifier.html
205
+
206
+ CocoaErrorDescriptions = [
207
+ ["NSReceiverEvaluationScriptError", "The object or objects specified by the direct parameter to a command could not be found."],
208
+ ["NSKeySpecifierEvaluationScriptError", "The object or objects specified by a key (for commands that support key specifiers) could not be found."],
209
+ ["NSArgumentEvaluationScriptError", "The object specified by an argument could not be found."],
210
+ ["NSReceiversCantHandleCommandScriptError", "The receivers don't support the command sent to them."],
211
+ ["NSRequiredArgumentsMissingScriptError", "An argument (or more than one argument) is missing."],
212
+ ["NSArgumentsWrongScriptError", "An argument (or more than one argument) is of the wrong type or is otherwise invalid."],
213
+ ["NSUnknownKeyScriptError", "An unidentified error occurred; indicates an error in the scripting support of the application."],
214
+ ["NSInternalScriptError", "An unidentified internal error occurred; indicates an error in the scripting support of the application."],
215
+ ["NSOperationNotSupportedForKeyScriptError", "The implementation of a scripting command signaled an error."],
216
+ ["NSCannotCreateScriptCommandError", "Could not create the script command; an invalid or unrecognized Apple event was received."],
217
+ ["NSNoSpecifierError", "No error encountered."],
218
+ ["NSNoTopLevelContainersSpecifierError", "Someone called evaluate with nil."],
219
+ ["NSContainerSpecifierError", "Error evaluating container specifier."],
220
+ ["NSUnknownKeySpecifierError", "Receivers do not understand the key."],
221
+ ["NSInvalidIndexSpecifierError", "Index out of bounds."],
222
+ ["NSInternalSpecifierError", "Other internal error."],
223
+ ["NSOperationNotSupportedForKeySpecifierError", "Attempt made to perform an unsupported operation on some key."]
224
+ ]
225
+
226
+ attr_reader :number, :raw
227
+ alias_method :to_i, :number
228
+
229
+ def initialize(number, reply_params={})
230
+ @number = number
231
+ @message = nil
232
+ @raw = reply_params
233
+ end
234
+
235
+ def message
236
+ if not @message
237
+ desc = @raw[KAE::KeyErrorString]
238
+ @message = DefaultCodecs.unpack(desc) if desc
239
+ if @message.is_a?(String) and @number > 0
240
+ # add clarification to default Cocoa Scripting error messages
241
+ CocoaErrorDescriptions.each do |name, description|
242
+ if @message[0, name.length] == name
243
+ @message += " (#{description})"
244
+ break
245
+ end
246
+ end
247
+ end
248
+ # if no message supplied or is a MacOSError, use default message if one is available
249
+ @message = MacOSErrorDescriptions.fetch(number, '') if @message == nil
250
+ end
251
+ return @message
252
+ end
253
+
254
+ def to_s
255
+ if message != ''
256
+ return "EventError\n\t\tOSERROR: #{number}\n\t\tMESSAGE: #{message}"
257
+ else
258
+ return "EventError\n\t\tOSERROR: #{number}"
259
+ end
260
+ end
261
+
262
+ # extended error info (some apps may return additional error info, though most don't)
263
+
264
+ def offending_object
265
+ desc = @raw[KAE::KOSAErrorOffendingObject]
266
+ return desc ? DefaultCodecs.unpack(desc) : nil
267
+ end
268
+
269
+ def expected_type
270
+ desc = @raw[KAE::KOSAErrorExpectedType]
271
+ return desc ? DefaultCodecs.unpack(desc) : nil
272
+ end
273
+
274
+ def partial_result
275
+ desc = @raw[KAE::KOSAErrorPartialResult]
276
+ return desc ? DefaultCodecs.unpack(desc) : nil
277
+ end
278
+ end
279
279
  end