rb-appscript 0.3.0 → 0.4.0
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/CHANGES +45 -0
- data/README +5 -1
- data/TODO +3 -23
- data/doc/aem-manual/04_references.html +6 -6
- data/doc/aem-manual/05_targettingapplications.html +3 -3
- data/doc/aem-manual/07_findapp.html +1 -1
- data/doc/appscript-manual/04_gettinghelp.html +81 -7
- data/doc/appscript-manual/05_keywordconversion.html +18 -18
- data/doc/appscript-manual/07_applicationobjects.html +4 -4
- data/doc/appscript-manual/08_realvsgenericreferences.html +2 -2
- data/doc/appscript-manual/09_referenceforms.html +12 -14
- data/doc/appscript-manual/11_applicationcommands.html +1 -1
- data/doc/appscript-manual/14_notes.html +12 -12
- data/doc/osax-manual/index.html +2 -0
- data/rb-appscript.gemspec +2 -2
- data/sample/AB_list_people_with_emails.rb +3 -0
- data/sample/Add_iCal_event.rb +3 -0
- data/sample/Create_daily_iCal_todos.rb +2 -0
- data/sample/Export_Address_Book_phone_numbers.rb +3 -0
- data/sample/Hello_world.rb +3 -0
- data/sample/List_iTunes_playlist_names.rb +3 -0
- data/sample/Make_Mail_message.rb +3 -0
- data/sample/Open_file_in_TextEdit.rb +3 -0
- data/sample/Organize_Mail_messages.rb +3 -0
- data/sample/Print_folder_tree.rb +3 -0
- data/sample/Select_all_HTML_files.rb +3 -0
- data/sample/Set_iChat_status.rb +3 -0
- data/sample/Simple_Finder_GUI_Scripting.rb +6 -3
- data/sample/Stagger_Finder_windows.rb +3 -0
- data/sample/TextEdit_demo.rb +3 -0
- data/sample/iTunes_top40_to_html.rb +3 -0
- data/src/SendThreadSafe.c +380 -0
- data/src/SendThreadSafe.h +139 -0
- data/src/lib/_aem/aemreference.rb +46 -18
- data/src/lib/_aem/codecs.rb +19 -3
- data/src/lib/_aem/mactypes.rb +2 -6
- data/src/lib/_aem/send.rb +1 -1
- data/src/lib/_aem/typewrappers.rb +2 -2
- data/src/lib/_appscript/referencerenderer.rb +10 -4
- data/src/lib/_appscript/reservedkeywords.rb +4 -4
- data/src/lib/_appscript/terminology.rb +43 -35
- data/src/lib/aem.rb +8 -4
- data/src/lib/appscript.rb +78 -15
- data/src/lib/kae.rb +4 -0
- data/src/lib/osax.rb +9 -6
- data/src/rbae.c +102 -23
- data/test/test_aemreference.rb +4 -4
- data/test/test_appscriptcommands.rb +2 -2
- data/test/test_appscriptreference.rb +4 -4
- data/test/test_codecs.rb +14 -1
- data/test/test_findapp.rb +1 -1
- data/test/test_mactypes.rb +1 -1
- data/test/test_osax.rb +1 -1
- data/test/testall.sh +1 -1
- metadata +4 -2
@@ -28,6 +28,9 @@ ReservedKeywords = [
|
|
28
28
|
"any",
|
29
29
|
"app",
|
30
30
|
"before",
|
31
|
+
"begin_transaction",
|
32
|
+
"beginning",
|
33
|
+
"begins_with",
|
31
34
|
"by_aem_app",
|
32
35
|
"by_creator",
|
33
36
|
"by_id",
|
@@ -43,7 +46,7 @@ ReservedKeywords = [
|
|
43
46
|
"display",
|
44
47
|
"does_not_contain",
|
45
48
|
"does_not_end_with",
|
46
|
-
"
|
49
|
+
"does_not_begin_with",
|
47
50
|
"dup",
|
48
51
|
"elements",
|
49
52
|
"end",
|
@@ -98,9 +101,6 @@ ReservedKeywords = [
|
|
98
101
|
"result_type",
|
99
102
|
"send",
|
100
103
|
"singleton_methods",
|
101
|
-
"start",
|
102
|
-
"start_transaction",
|
103
|
-
"starts_with",
|
104
104
|
"taint",
|
105
105
|
"tainted?",
|
106
106
|
"timeout",
|
@@ -8,6 +8,8 @@
|
|
8
8
|
|
9
9
|
module TerminologyParser
|
10
10
|
|
11
|
+
require "ae"
|
12
|
+
require "kae"
|
11
13
|
require "_appscript/reservedkeywords" # names of all existing methods on ASReference::Application
|
12
14
|
|
13
15
|
class BigEndianParser
|
@@ -204,11 +206,10 @@ module TerminologyParser
|
|
204
206
|
|
205
207
|
def parse(aetes)
|
206
208
|
aetes.each do |aete|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
raise RuntimeError, "aete was not fully parsed."
|
209
|
+
if aete.is_a?(AE::AEDesc) and aete.type == KAE::TypeAETE and aete.data != ''
|
210
|
+
@_str = aete.data
|
211
|
+
@_ptr = 6 # version, language, script integers
|
212
|
+
_integer.times { parse_suite }
|
212
213
|
end
|
213
214
|
end
|
214
215
|
# singular names are normally used in the classes table and plural names in the elements table. However, if an aete defines a singular name but not a plural name then the missing plural name is substituted with the singular name; and vice-versa if there's no singular equivalent for a plural name.
|
@@ -322,7 +323,8 @@ module Terminology
|
|
322
323
|
def Terminology.tables_for_aetes(aetes)
|
323
324
|
# Build terminology tables from a list of unpacked aete byte strings.
|
324
325
|
# Result : list of hash -- [typebycode, typebyname, referencebycode, referencebyname]
|
325
|
-
|
326
|
+
aetes = aetes.reject { |aete| not (aete.is_a?(AE::AEDesc) and aete.type == KAE::TypeAETE and aete.data != '') }
|
327
|
+
classes, enums, properties, elements, commands = TerminologyParser.build_tables_for_aetes(aetes)
|
326
328
|
return _make_type_table(classes, enums, properties) + _make_reference_table(properties, elements, commands)
|
327
329
|
end
|
328
330
|
|
@@ -338,27 +340,30 @@ module Terminology
|
|
338
340
|
+ _make_reference_table(terms::Properties, terms::Elements, terms::Commands)
|
339
341
|
end
|
340
342
|
|
343
|
+
def Terminology.aetes_for_app(aem_app)
|
344
|
+
begin
|
345
|
+
begin
|
346
|
+
aetes = aem_app.event('ascrgdte', {'----' => 0}).send(120 * 60)
|
347
|
+
rescue AEM::CommandError => e
|
348
|
+
if e.number == -192 # aete resource not found
|
349
|
+
aetes = []
|
350
|
+
else
|
351
|
+
raise
|
352
|
+
end
|
353
|
+
end
|
354
|
+
rescue => err
|
355
|
+
raise RuntimeError, "Can't get terminology for application (#{aem_app}): #{err}"
|
356
|
+
end
|
357
|
+
aetes = [aetes] if not aetes.is_a?(Array)
|
358
|
+
return aetes
|
359
|
+
end
|
360
|
+
|
341
361
|
def Terminology.tables_for_app(aem_app)
|
342
362
|
# Build terminology tables for an application.
|
343
363
|
# app : AEM::Application
|
344
364
|
# Result : list of hash -- [typebycode, typebyname, referencebycode, referencebyname]
|
345
365
|
if not @@_terminology_cache.has_key?(aem_app.identity)
|
346
|
-
|
347
|
-
begin
|
348
|
-
aetes = aem_app.event('ascrgdte', {'----' => 0}).send(60 * 60)
|
349
|
-
rescue AEM::CommandError => e
|
350
|
-
if e.number == -192 # aete resource not found
|
351
|
-
aetes = []
|
352
|
-
else
|
353
|
-
raise
|
354
|
-
end
|
355
|
-
end
|
356
|
-
if not aetes.is_a?(Array)
|
357
|
-
aetes = [aetes]
|
358
|
-
end
|
359
|
-
rescue => err
|
360
|
-
raise RuntimeError, "Can't get terminology for application (#{aem_app}): #{err}"
|
361
|
-
end
|
366
|
+
aetes = Terminology.aetes_for_app(aem_app)
|
362
367
|
@@_terminology_cache[aem_app.identity] = Terminology.tables_for_aetes(aetes)
|
363
368
|
end
|
364
369
|
return @@_terminology_cache[aem_app.identity]
|
@@ -375,22 +380,25 @@ module Terminology
|
|
375
380
|
if not /^[A-Z][A-Za-z0-9_]*$/ === module_name
|
376
381
|
raise RuntimeError, "Invalid module name."
|
377
382
|
end
|
378
|
-
#
|
379
|
-
|
380
|
-
# Get aete(s)
|
383
|
+
# Get aete(s)
|
384
|
+
begin
|
381
385
|
begin
|
382
386
|
aetes = AEM::Codecs.new.unpack(AE.get_app_terminology(app_path).coerce(KAE::TypeAEList))
|
383
|
-
rescue
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
387
|
+
rescue NotImplementedError # get_app_terminology is unavailable on 64-bit Leopard
|
388
|
+
aetes = Terminology.aetes_for_app(AEM::Application.by_path(app_path))
|
389
|
+
end
|
390
|
+
rescue AE::MacOSError => e
|
391
|
+
if e.to_i == -192 # aete resource not found
|
392
|
+
raise RuntimeError, "No terminology found."
|
393
|
+
else
|
394
|
+
raise
|
389
395
|
end
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
396
|
+
end
|
397
|
+
aetes.delete_if { |aete| not (aete.is_a?(AE::AEDesc) and aete.type == KAE::TypeAETE) }
|
398
|
+
# Parse aete(s) into intermediate tables, suitable for use by Terminology#tables_for_module
|
399
|
+
tables = TerminologyParser.build_tables_for_aetes(aetes)
|
400
|
+
# Write module
|
401
|
+
File.open(out_path, "w") do |f|
|
394
402
|
f.puts "module #{module_name}"
|
395
403
|
f.puts "\tVersion = 1.1"
|
396
404
|
f.puts "\tPath = #{app_path.inspect}"
|
data/src/lib/aem.rb
CHANGED
@@ -49,6 +49,10 @@ module AEM
|
|
49
49
|
return AEMReference::Its
|
50
50
|
end
|
51
51
|
|
52
|
+
def AEM.custom_root(value)
|
53
|
+
return AEMReference::CustomRoot.new(value)
|
54
|
+
end
|
55
|
+
|
52
56
|
#######
|
53
57
|
# Application class
|
54
58
|
|
@@ -140,10 +144,10 @@ module AEM
|
|
140
144
|
|
141
145
|
def inspect
|
142
146
|
if @identity[0] == :current
|
143
|
-
return
|
147
|
+
return "#{self.class}.current"
|
144
148
|
else
|
145
149
|
con_name = {:path => 'by_path', :url => 'by_url', :pid => 'by_pid', :desc => 'by_desc'}[@identity[0]]
|
146
|
-
return "
|
150
|
+
return "#{self.class}.#{con_name}(#{@identity[1].inspect})"
|
147
151
|
end
|
148
152
|
end
|
149
153
|
|
@@ -180,8 +184,8 @@ module AEM
|
|
180
184
|
return self.class::Event.new(@address_desc, event, params, atts, @_transaction, return_id, codecs)
|
181
185
|
end
|
182
186
|
|
183
|
-
def
|
184
|
-
#
|
187
|
+
def begin_transaction(session=nil)
|
188
|
+
# Begin a new transaction.
|
185
189
|
if @_transaction != KAE::KAnyTransactionID
|
186
190
|
raise RuntimeError, "Transaction is already active."
|
187
191
|
end
|
data/src/lib/appscript.rb
CHANGED
@@ -11,6 +11,7 @@ module Appscript
|
|
11
11
|
|
12
12
|
require "kae"
|
13
13
|
require "aem"
|
14
|
+
require "_aem/aemreference"
|
14
15
|
require "_appscript/referencerenderer"
|
15
16
|
require "_appscript/terminology"
|
16
17
|
require "_appscript/safeobject"
|
@@ -25,6 +26,8 @@ module Appscript
|
|
25
26
|
|
26
27
|
class AppData < AEM::Codecs
|
27
28
|
|
29
|
+
HelpAgentID = 'net.sourceforge.appscript.appscripthelpagent'
|
30
|
+
|
28
31
|
attr_reader :constructor, :identifier, :reference_codecs
|
29
32
|
attr_writer :reference_codecs
|
30
33
|
|
@@ -35,6 +38,7 @@ module Appscript
|
|
35
38
|
@constructor = constructor # name of AEM::Application constructor to use/:by_aem_app
|
36
39
|
@identifier = identifier # argument for AEM::Application constructor
|
37
40
|
@reference_codecs = AEM::Codecs.new # low-level Codecs object used to unpack references; used by AppData#unpack_object_specifier, AppData#unpack_insertion_loc. Note: this is a bit kludgy, and it's be better to use AppData for all unpacking, but it should be 'good enough' in practice.
|
41
|
+
@_help_agent = nil
|
38
42
|
end
|
39
43
|
|
40
44
|
def connect # initialize AEM::Application instance and terminology tables the first time they are needed
|
@@ -63,6 +67,54 @@ module Appscript
|
|
63
67
|
|
64
68
|
#######
|
65
69
|
|
70
|
+
Constructors = {
|
71
|
+
:by_path => 'path',
|
72
|
+
:by_pid => 'pid',
|
73
|
+
:by_url => 'url',
|
74
|
+
:by_aem_app => 'aemapp',
|
75
|
+
:current => 'current',
|
76
|
+
}
|
77
|
+
|
78
|
+
def _make_help_agent
|
79
|
+
begin
|
80
|
+
@_help_agent = AEM::Application.by_path(FindApp.by_id(HelpAgentID))
|
81
|
+
return true
|
82
|
+
rescue FindApp::ApplicationNotFoundError
|
83
|
+
puts "No help available: AppscriptHelpAgent.app not found."
|
84
|
+
return false
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def _display_help(flags, ref)
|
89
|
+
begin
|
90
|
+
puts @_help_agent.event('ASHAHelp', {
|
91
|
+
'Cons' => Constructors[@constructor],
|
92
|
+
'Iden' => @constructor == :by_aem_app ? @identifier.address_desc : @identifier,
|
93
|
+
'Styl' => 'rb-appscript',
|
94
|
+
'Flag' => flags,
|
95
|
+
'aRef' => pack(ref),
|
96
|
+
}).send
|
97
|
+
return nil
|
98
|
+
rescue AEM::CommandError => e
|
99
|
+
return e
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def help(flags, ref)
|
104
|
+
if not @_help_agent
|
105
|
+
return ref if not _make_help_agent
|
106
|
+
end
|
107
|
+
e = _display_help(flags, ref)
|
108
|
+
if e and [-600, -609].include?(e.number) # not running
|
109
|
+
return ref if not _make_help_agent
|
110
|
+
e = _display_help(flags, ref)
|
111
|
+
end
|
112
|
+
puts "No help available: AppscriptHelpAgent raised an error: #{e}." if e
|
113
|
+
return ref
|
114
|
+
end
|
115
|
+
|
116
|
+
#######
|
117
|
+
|
66
118
|
def target
|
67
119
|
connect
|
68
120
|
return @target
|
@@ -309,6 +361,10 @@ module Appscript
|
|
309
361
|
|
310
362
|
#######
|
311
363
|
|
364
|
+
def help(flags='-t')
|
365
|
+
return @AS_app_data.help(flags, self)
|
366
|
+
end
|
367
|
+
|
312
368
|
def Reference._pack_uint32(n) # used to pack csig attributes
|
313
369
|
return AE::AEDesc.new(KAE::TypeUInt32, [n].pack('L'))
|
314
370
|
end
|
@@ -541,13 +597,18 @@ module Appscript
|
|
541
597
|
new_ref = @AS_aem_reference.by_range(
|
542
598
|
self._resolve_range_boundary(selector, 1),
|
543
599
|
self._resolve_range_boundary(end_range_selector, -1))
|
544
|
-
elsif selector.is_a?(String)
|
545
|
-
new_ref = @AS_aem_reference.by_name(selector)
|
546
|
-
elsif selector.is_a?(Appscript::GenericReference)
|
547
|
-
new_ref = @AS_aem_reference.by_filter(
|
548
|
-
selector.AS_resolve(@AS_app_data).AS_aem_reference)
|
549
600
|
else
|
550
|
-
|
601
|
+
case selector
|
602
|
+
when String
|
603
|
+
new_ref = @AS_aem_reference.by_name(selector)
|
604
|
+
when Appscript::GenericReference
|
605
|
+
new_ref = @AS_aem_reference.by_filter(
|
606
|
+
selector.AS_resolve(@AS_app_data).AS_aem_reference)
|
607
|
+
when Appscript::Reference, AEMReference::Test
|
608
|
+
new_ref = @AS_aem_reference.by_filter(selector)
|
609
|
+
else
|
610
|
+
new_ref = @AS_aem_reference.by_index(selector)
|
611
|
+
end
|
551
612
|
end
|
552
613
|
return Reference.new(@AS_app_data, new_ref)
|
553
614
|
end
|
@@ -568,8 +629,8 @@ module Appscript
|
|
568
629
|
return Reference.new(@AS_app_data, @AS_aem_reference.any)
|
569
630
|
end
|
570
631
|
|
571
|
-
def
|
572
|
-
return Reference.new(@AS_app_data, @AS_aem_reference.
|
632
|
+
def beginning
|
633
|
+
return Reference.new(@AS_app_data, @AS_aem_reference.beginning)
|
573
634
|
end
|
574
635
|
|
575
636
|
def end
|
@@ -625,8 +686,8 @@ module Appscript
|
|
625
686
|
return Reference.new(@AS_app_data, @AS_aem_reference.le(operand))
|
626
687
|
end
|
627
688
|
|
628
|
-
def
|
629
|
-
return Reference.new(@AS_app_data, @AS_aem_reference.
|
689
|
+
def begins_with(operand)
|
690
|
+
return Reference.new(@AS_app_data, @AS_aem_reference.begins_with(operand))
|
630
691
|
end
|
631
692
|
|
632
693
|
def ends_with(operand)
|
@@ -641,8 +702,8 @@ module Appscript
|
|
641
702
|
return Reference.new(@AS_app_data, @AS_aem_reference.is_in(operand))
|
642
703
|
end
|
643
704
|
|
644
|
-
def
|
645
|
-
return self.
|
705
|
+
def does_not_begin_with(operand)
|
706
|
+
return self.begins_with(operand).not
|
646
707
|
end
|
647
708
|
|
648
709
|
def does_not_end_with(operand)
|
@@ -722,13 +783,15 @@ module Appscript
|
|
722
783
|
def AS_new_reference(ref)
|
723
784
|
if ref.is_a?(Appscript::GenericReference)
|
724
785
|
return ref.AS_resolve(@AS_app_data)
|
725
|
-
|
786
|
+
elsif ref.is_a?(AEMReference::Base)
|
726
787
|
return Reference.new(@AS_app_data, ref)
|
788
|
+
else
|
789
|
+
return Reference.new(@AS_app_data, AEM.custom_root(ref))
|
727
790
|
end
|
728
791
|
end
|
729
792
|
|
730
|
-
def
|
731
|
-
@AS_app_data.target.
|
793
|
+
def begin_transaction(session=nil)
|
794
|
+
@AS_app_data.target.begin_transaction(session)
|
732
795
|
end
|
733
796
|
|
734
797
|
def abort_transaction
|
data/src/lib/kae.rb
CHANGED
data/src/lib/osax.rb
CHANGED
@@ -5,6 +5,9 @@ require "appscript"
|
|
5
5
|
module OSAX
|
6
6
|
|
7
7
|
# Allows scripting additions (a.k.a. OSAXen) to be called from Ruby.
|
8
|
+
#
|
9
|
+
# Note: currently 32-bit only; attempting to create a new ScriptingAddition instance
|
10
|
+
# in a 64-bit process will result in a NotImplementedError.
|
8
11
|
|
9
12
|
######################################################################
|
10
13
|
# PRIVATE
|
@@ -131,13 +134,13 @@ module OSAX
|
|
131
134
|
if not path
|
132
135
|
raise ArgumentError, "Scripting addition not found: #{name.inspect}"
|
133
136
|
end
|
134
|
-
if terms
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
Terminology.tables_for_aetes(DefaultCodecs.unpack(desc))
|
137
|
+
if not terms
|
138
|
+
aetes_desc = AE.get_app_terminology(path) # will raise NotImplementedError in 64-bit processes
|
139
|
+
aetes = DefaultCodecs.unpack(aetes_desc.coerce(KAE::TypeAEList))
|
140
|
+
terms = Terminology.tables_for_aetes(aetes)
|
141
|
+
OSAXCache[osax_name][1] = terms
|
140
142
|
end
|
143
|
+
@_terms = terms
|
141
144
|
osax_data = OSAXData.new(:current, nil, @_terms)
|
142
145
|
end
|
143
146
|
super(osax_data, AEM.app)
|
data/src/rbae.c
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
/*
|
2
2
|
* Copyright (C) 2006 HAS
|
3
3
|
*
|
4
|
-
* Thanks to:
|
4
|
+
* Thanks to:
|
5
|
+
* - FUJIMOTO Hisakuni, author of RubyAEOSA
|
6
|
+
* - Jordan Breeding (64-bit support patch)
|
5
7
|
*/
|
6
8
|
|
7
9
|
#include "osx_ruby.h"
|
8
10
|
#include <Carbon/Carbon.h>
|
11
|
+
#include <CoreFoundation/CoreFoundation.h>
|
12
|
+
#include "SendThreadSafe.h"
|
9
13
|
|
10
14
|
VALUE rb_ll2big(LONG_LONG); // keeps gcc happy
|
11
15
|
|
@@ -24,7 +28,11 @@ struct rbAE_AEDescWrapper {
|
|
24
28
|
#define AEDESC_OF(o) (AEDESC_DATA_PTR(o)->desc)
|
25
29
|
|
26
30
|
// Event handling
|
27
|
-
|
31
|
+
#if __LP64__
|
32
|
+
// SRefCon typedefed as void * by system headers
|
33
|
+
#else
|
34
|
+
typedef long SRefCon;
|
35
|
+
#endif
|
28
36
|
|
29
37
|
AEEventHandlerUPP upp_GenericEventHandler;
|
30
38
|
AECoercionHandlerUPP upp_GenericCoercionHandler;
|
@@ -60,7 +68,7 @@ rbAE_MacOSError_inspect(VALUE self)
|
|
60
68
|
{
|
61
69
|
char s[32];
|
62
70
|
|
63
|
-
sprintf(s, "#<AE::MacOSError %
|
71
|
+
sprintf(s, "#<AE::MacOSError %li>", (long)NUM2INT(rb_iv_get(self, "@number")));
|
64
72
|
return rb_str_new2(s);
|
65
73
|
}
|
66
74
|
|
@@ -175,6 +183,19 @@ rbAE_AEDesc_newAppleEvent(VALUE class, VALUE eventClass, VALUE eventID,
|
|
175
183
|
}
|
176
184
|
|
177
185
|
|
186
|
+
static VALUE
|
187
|
+
rbAE_AEDesc_newUnflatten(VALUE class, VALUE data)
|
188
|
+
{
|
189
|
+
OSErr err = noErr;
|
190
|
+
AEDesc desc;
|
191
|
+
|
192
|
+
Check_Type(data, T_STRING);
|
193
|
+
err = AEUnflattenDesc(RSTRING(data)->ptr, &desc);
|
194
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't create AEDesc.", err);
|
195
|
+
return rbAE_wrapAEDesc(&desc);
|
196
|
+
}
|
197
|
+
|
198
|
+
|
178
199
|
/**********************************************************************/
|
179
200
|
// AEDesc methods
|
180
201
|
|
@@ -225,6 +246,24 @@ rbAE_AEDesc_data(VALUE self)
|
|
225
246
|
}
|
226
247
|
|
227
248
|
|
249
|
+
static VALUE
|
250
|
+
rbAE_AEDesc_flatten(VALUE self)
|
251
|
+
{
|
252
|
+
OSErr err = noErr;
|
253
|
+
Size dataSize;
|
254
|
+
void *data;
|
255
|
+
VALUE result;
|
256
|
+
|
257
|
+
dataSize = AESizeOfFlattenedDesc(&(AEDESC_OF(self)));
|
258
|
+
data = malloc(dataSize);
|
259
|
+
err = AEFlattenDesc(&(AEDESC_OF(self)), data, dataSize, NULL);
|
260
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't flatten AEDesc.", err);
|
261
|
+
result = rb_str_new(data, dataSize);
|
262
|
+
free(data);
|
263
|
+
return result;
|
264
|
+
}
|
265
|
+
|
266
|
+
|
228
267
|
/*******/
|
229
268
|
|
230
269
|
static VALUE
|
@@ -328,9 +367,9 @@ rbAE_AEDesc_getParam(VALUE self, VALUE key, VALUE type)
|
|
328
367
|
AEDesc desc;
|
329
368
|
|
330
369
|
err = AEGetParamDesc(&(AEDESC_OF(self)),
|
331
|
-
|
332
|
-
|
333
|
-
|
370
|
+
rbStringToDescType(key),
|
371
|
+
rbStringToDescType(type),
|
372
|
+
&desc);
|
334
373
|
if (err != noErr) rbAE_raiseMacOSError("Can't get parameter from AEDesc.", err);
|
335
374
|
return rbAE_wrapAEDesc(&desc);
|
336
375
|
}
|
@@ -343,9 +382,9 @@ rbAE_AEDesc_getAttr(VALUE self, VALUE key, VALUE type)
|
|
343
382
|
AEDesc desc;
|
344
383
|
|
345
384
|
err = AEGetAttributeDesc(&(AEDESC_OF(self)),
|
346
|
-
|
347
|
-
|
348
|
-
|
385
|
+
rbStringToDescType(key),
|
386
|
+
rbStringToDescType(type),
|
387
|
+
&desc);
|
349
388
|
if (err != noErr) rbAE_raiseMacOSError("Can't get attribute from AEDesc.", err);
|
350
389
|
return rbAE_wrapAEDesc(&desc);
|
351
390
|
}
|
@@ -367,6 +406,20 @@ rbAE_AEDesc_send(VALUE self, VALUE sendMode, VALUE timeout)
|
|
367
406
|
return rbAE_wrapAEDesc(&reply);
|
368
407
|
}
|
369
408
|
|
409
|
+
static VALUE
|
410
|
+
rbAE_AEDesc_sendThreadSafe(VALUE self, VALUE sendMode, VALUE timeout)
|
411
|
+
{
|
412
|
+
OSErr err = noErr;
|
413
|
+
AppleEvent reply;
|
414
|
+
|
415
|
+
err = SendMessageThreadSafe(&(AEDESC_OF(self)),
|
416
|
+
&reply,
|
417
|
+
(AESendMode)NUM2LONG(sendMode),
|
418
|
+
NUM2LONG(timeout));
|
419
|
+
if (err != noErr) rbAE_raiseMacOSError("Can't send Apple event.", err);
|
420
|
+
return rbAE_wrapAEDesc(&reply);
|
421
|
+
}
|
422
|
+
|
370
423
|
|
371
424
|
/**********************************************************************/
|
372
425
|
// Find and launch applications
|
@@ -444,7 +497,9 @@ static VALUE
|
|
444
497
|
rbAE_launchApplication(VALUE self, VALUE path, VALUE firstEvent, VALUE flags)
|
445
498
|
{
|
446
499
|
FSRef appRef;
|
447
|
-
|
500
|
+
#if !defined(__LP64__)
|
501
|
+
FSSpec appFSS;
|
502
|
+
#endif
|
448
503
|
AEDesc paraDesc;
|
449
504
|
Size paraSize;
|
450
505
|
AppParametersPtr paraData;
|
@@ -454,8 +509,10 @@ rbAE_launchApplication(VALUE self, VALUE path, VALUE firstEvent, VALUE flags)
|
|
454
509
|
|
455
510
|
err = FSPathMakeRef((UInt8 *)StringValuePtr(path), &appRef, NULL);
|
456
511
|
if (err != 0) rbAE_raiseMacOSError("Couldn't make FSRef for application.", err);
|
457
|
-
|
512
|
+
#if !defined(__LP64__)
|
513
|
+
err = FSGetCatalogInfo(&appRef, kFSCatInfoNone, NULL, NULL, &appFSS, NULL);
|
458
514
|
if (err != 0) rbAE_raiseMacOSError("Couldn't make FSSpec for application.", err);
|
515
|
+
#endif
|
459
516
|
err = AECoerceDesc(&(AEDESC_OF(firstEvent)), typeAppParameters, ¶Desc);
|
460
517
|
paraSize = AEGetDescDataSize(¶Desc);
|
461
518
|
paraData = (AppParametersPtr)NewPtr(paraSize);
|
@@ -466,7 +523,11 @@ rbAE_launchApplication(VALUE self, VALUE path, VALUE firstEvent, VALUE flags)
|
|
466
523
|
launchParams.launchEPBLength = extendedBlockLen;
|
467
524
|
launchParams.launchFileFlags = 0;
|
468
525
|
launchParams.launchControlFlags = (LaunchFlags)NUM2UINT(flags);
|
469
|
-
|
526
|
+
#if defined(__LP64__)
|
527
|
+
launchParams.launchAppRef = &appRef;
|
528
|
+
#else
|
529
|
+
launchParams.launchAppSpec = &appFSS;
|
530
|
+
#endif
|
470
531
|
launchParams.launchAppParameters = paraData;
|
471
532
|
err = LaunchApplication(&launchParams);
|
472
533
|
if (err != noErr) rbAE_raiseMacOSError("Can't launch application.", err);
|
@@ -507,6 +568,10 @@ rbAE_convertUnixSecondsToLongDateTime(VALUE self, VALUE secs)
|
|
507
568
|
static VALUE
|
508
569
|
rbAE_OSAGetAppTerminology(VALUE self, VALUE path)
|
509
570
|
{
|
571
|
+
#if defined(__LP64__)
|
572
|
+
rb_raise(rb_eNotImpError, "AE.get_app_terminology isn't available in 64-bit processes.\n");
|
573
|
+
return Qnil;
|
574
|
+
#else
|
510
575
|
FSRef appRef;
|
511
576
|
FSSpec fss;
|
512
577
|
ComponentInstance defaultComponent;
|
@@ -514,6 +579,8 @@ rbAE_OSAGetAppTerminology(VALUE self, VALUE path)
|
|
514
579
|
AEDesc theDesc;
|
515
580
|
OSErr err = noErr;
|
516
581
|
|
582
|
+
if (OSAGetAppTerminology == NULL)
|
583
|
+
rb_raise(rb_eNotImpError, "OSAGetAppTerminology unavailable.\n");
|
517
584
|
err = FSPathMakeRef((UInt8 *)StringValuePtr(path), &appRef, NULL);
|
518
585
|
if (err != 0) rbAE_raiseMacOSError("Couldn't make FSRef.", err);
|
519
586
|
err = FSGetCatalogInfo(&appRef, kFSCatInfoNone, NULL, NULL, &fss, NULL);
|
@@ -529,6 +596,7 @@ rbAE_OSAGetAppTerminology(VALUE self, VALUE path)
|
|
529
596
|
&theDesc);
|
530
597
|
if (err != 0) rbAE_raiseMacOSError("Couldn't get aete resource.", err);
|
531
598
|
return rbAE_wrapAEDesc(&theDesc);
|
599
|
+
#endif
|
532
600
|
}
|
533
601
|
|
534
602
|
|
@@ -540,7 +608,7 @@ rbAE_OSAGetAppTerminology(VALUE self, VALUE path)
|
|
540
608
|
// TO DO: make sure GC won't collect handler objects while they're installed as event/coercion handlers
|
541
609
|
|
542
610
|
static pascal OSErr
|
543
|
-
rbAE_GenericEventHandler(const AppleEvent *request, AppleEvent *reply,
|
611
|
+
rbAE_GenericEventHandler(const AppleEvent *request, AppleEvent *reply, SRefCon refcon)
|
544
612
|
{
|
545
613
|
VALUE err;
|
546
614
|
|
@@ -555,7 +623,7 @@ rbAE_GenericEventHandler(const AppleEvent *request, AppleEvent *reply, refcontyp
|
|
555
623
|
/*******/
|
556
624
|
|
557
625
|
static VALUE
|
558
|
-
rbAE_AEInstallEventHandler(VALUE self, VALUE eventClass, VALUE eventID,
|
626
|
+
rbAE_AEInstallEventHandler(VALUE self, VALUE eventClass, VALUE eventID, SRefCon handler)
|
559
627
|
{
|
560
628
|
/*
|
561
629
|
* eventClass and eventID must be four-character code strings
|
@@ -569,7 +637,7 @@ rbAE_AEInstallEventHandler(VALUE self, VALUE eventClass, VALUE eventID, VALUE ha
|
|
569
637
|
|
570
638
|
err = AEInstallEventHandler(rbStringToDescType(eventClass),
|
571
639
|
rbStringToDescType(eventID),
|
572
|
-
upp_GenericEventHandler,
|
640
|
+
upp_GenericEventHandler, handler,
|
573
641
|
0);
|
574
642
|
if (err != noErr) rbAE_raiseMacOSError("Can't install event handler.", err);
|
575
643
|
return Qnil;
|
@@ -595,14 +663,14 @@ rbAE_AEGetEventHandler(VALUE self, VALUE eventClass, VALUE eventID)
|
|
595
663
|
{
|
596
664
|
OSErr err = noErr;
|
597
665
|
AEEventHandlerUPP handlerUPP;
|
598
|
-
|
666
|
+
SRefCon handler;
|
599
667
|
|
600
668
|
err = AEGetEventHandler(rbStringToDescType(eventClass),
|
601
669
|
rbStringToDescType(eventID),
|
602
|
-
&handlerUPP,
|
670
|
+
&handlerUPP, &handler,
|
603
671
|
0);
|
604
672
|
if (err != noErr) rbAE_raiseMacOSError("Can't get event handler.", err);
|
605
|
-
return handler;
|
673
|
+
return (VALUE)handler;
|
606
674
|
}
|
607
675
|
|
608
676
|
|
@@ -612,7 +680,7 @@ rbAE_AEGetEventHandler(VALUE self, VALUE eventClass, VALUE eventID)
|
|
612
680
|
// TO DO: make sure GC won't collect handler objects while they're installed as event/coercion handlers
|
613
681
|
|
614
682
|
static pascal OSErr
|
615
|
-
rbAE_GenericCoercionHandler(const AEDesc *fromDesc, DescType toType,
|
683
|
+
rbAE_GenericCoercionHandler(const AEDesc *fromDesc, DescType toType, SRefCon refcon, AEDesc *toDesc)
|
616
684
|
{
|
617
685
|
// handle_coercion method should return an AE::AEDesc, or nil if an error occurred
|
618
686
|
OSErr err = noErr;
|
@@ -632,7 +700,7 @@ rbAE_GenericCoercionHandler(const AEDesc *fromDesc, DescType toType, refcontype
|
|
632
700
|
/*******/
|
633
701
|
|
634
702
|
static VALUE
|
635
|
-
rbAE_AEInstallCoercionHandler(VALUE self, VALUE fromType, VALUE toType,
|
703
|
+
rbAE_AEInstallCoercionHandler(VALUE self, VALUE fromType, VALUE toType, SRefCon handler)
|
636
704
|
{
|
637
705
|
/*
|
638
706
|
* fromType and toType must be four-character code strings
|
@@ -647,7 +715,7 @@ rbAE_AEInstallCoercionHandler(VALUE self, VALUE fromType, VALUE toType, VALUE ha
|
|
647
715
|
|
648
716
|
err = AEInstallCoercionHandler(rbStringToDescType(fromType),
|
649
717
|
rbStringToDescType(toType),
|
650
|
-
upp_GenericCoercionHandler,
|
718
|
+
upp_GenericCoercionHandler, handler,
|
651
719
|
1, 0);
|
652
720
|
if (err != noErr) rbAE_raiseMacOSError("Can't install coercion handler.", err);
|
653
721
|
return Qnil;
|
@@ -673,12 +741,12 @@ rbAE_AEGetCoercionHandler(VALUE self, VALUE fromType, VALUE toType)
|
|
673
741
|
{
|
674
742
|
OSErr err = noErr;
|
675
743
|
AECoercionHandlerUPP handlerUPP;
|
676
|
-
|
744
|
+
SRefCon handler;
|
677
745
|
Boolean fromTypeIsDesc;
|
678
746
|
|
679
747
|
err = AEGetCoercionHandler(rbStringToDescType(fromType),
|
680
748
|
rbStringToDescType(toType),
|
681
|
-
&handlerUPP,
|
749
|
+
&handlerUPP, &handler,
|
682
750
|
&fromTypeIsDesc,
|
683
751
|
0);
|
684
752
|
if (err != noErr) rbAE_raiseMacOSError("Can't get coercion handler.", err);
|
@@ -694,14 +762,22 @@ rbAE_AEGetCoercionHandler(VALUE self, VALUE fromType, VALUE toType)
|
|
694
762
|
static VALUE
|
695
763
|
rbAE_RunApplicationEventLoop(VALUE self)
|
696
764
|
{
|
765
|
+
#if defined(__LP64__)
|
766
|
+
rb_raise(rb_eNotImpError, "AE.run_application_event_loop isn't available in 64-bit processes.\n");
|
767
|
+
#else
|
697
768
|
RunApplicationEventLoop();
|
769
|
+
#endif
|
698
770
|
return Qnil;
|
699
771
|
}
|
700
772
|
|
701
773
|
static VALUE
|
702
774
|
rbAE_QuitApplicationEventLoop(VALUE self)
|
703
775
|
{
|
776
|
+
#if defined(__LP64__)
|
777
|
+
rb_raise(rb_eNotImpError, "AE.quit_application_event_loop isn't available in 64-bit processes.\n");
|
778
|
+
#else
|
704
779
|
QuitApplicationEventLoop();
|
780
|
+
#endif
|
705
781
|
return Qnil;
|
706
782
|
}
|
707
783
|
|
@@ -733,11 +809,13 @@ Init_ae (void)
|
|
733
809
|
rb_define_singleton_method(cAEDesc, "new", rbAE_AEDesc_new, 2);
|
734
810
|
rb_define_singleton_method(cAEDesc, "new_list", rbAE_AEDesc_newList, 1);
|
735
811
|
rb_define_singleton_method(cAEDesc, "new_apple_event", rbAE_AEDesc_newAppleEvent, 5);
|
812
|
+
rb_define_singleton_method(cAEDesc, "unflatten", rbAE_AEDesc_newUnflatten, 1);
|
736
813
|
|
737
814
|
rb_define_method(cAEDesc, "to_s", rbAE_AEDesc_inspect, 0);
|
738
815
|
rb_define_method(cAEDesc, "inspect", rbAE_AEDesc_inspect, 0);
|
739
816
|
rb_define_method(cAEDesc, "type", rbAE_AEDesc_type, 0);
|
740
817
|
rb_define_method(cAEDesc, "data", rbAE_AEDesc_data, 0);
|
818
|
+
rb_define_method(cAEDesc, "flatten", rbAE_AEDesc_flatten, 0);
|
741
819
|
rb_define_method(cAEDesc, "is_record?", rbAE_AEDesc_isRecord, 0);
|
742
820
|
rb_define_method(cAEDesc, "coerce", rbAE_AEDesc_coerce, 1);
|
743
821
|
rb_define_method(cAEDesc, "length", rbAE_AEDesc_length, 0);
|
@@ -748,6 +826,7 @@ Init_ae (void)
|
|
748
826
|
rb_define_method(cAEDesc, "get_param", rbAE_AEDesc_getParam, 2);
|
749
827
|
rb_define_method(cAEDesc, "get_attr", rbAE_AEDesc_getAttr, 2);
|
750
828
|
rb_define_method(cAEDesc, "send", rbAE_AEDesc_send, 2);
|
829
|
+
rb_define_method(cAEDesc, "send_thread_safe", rbAE_AEDesc_sendThreadSafe, 2);
|
751
830
|
|
752
831
|
// AE::MacOSError
|
753
832
|
|