rb-appscript 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/CHANGES +45 -0
  2. data/README +5 -1
  3. data/TODO +3 -23
  4. data/doc/aem-manual/04_references.html +6 -6
  5. data/doc/aem-manual/05_targettingapplications.html +3 -3
  6. data/doc/aem-manual/07_findapp.html +1 -1
  7. data/doc/appscript-manual/04_gettinghelp.html +81 -7
  8. data/doc/appscript-manual/05_keywordconversion.html +18 -18
  9. data/doc/appscript-manual/07_applicationobjects.html +4 -4
  10. data/doc/appscript-manual/08_realvsgenericreferences.html +2 -2
  11. data/doc/appscript-manual/09_referenceforms.html +12 -14
  12. data/doc/appscript-manual/11_applicationcommands.html +1 -1
  13. data/doc/appscript-manual/14_notes.html +12 -12
  14. data/doc/osax-manual/index.html +2 -0
  15. data/rb-appscript.gemspec +2 -2
  16. data/sample/AB_list_people_with_emails.rb +3 -0
  17. data/sample/Add_iCal_event.rb +3 -0
  18. data/sample/Create_daily_iCal_todos.rb +2 -0
  19. data/sample/Export_Address_Book_phone_numbers.rb +3 -0
  20. data/sample/Hello_world.rb +3 -0
  21. data/sample/List_iTunes_playlist_names.rb +3 -0
  22. data/sample/Make_Mail_message.rb +3 -0
  23. data/sample/Open_file_in_TextEdit.rb +3 -0
  24. data/sample/Organize_Mail_messages.rb +3 -0
  25. data/sample/Print_folder_tree.rb +3 -0
  26. data/sample/Select_all_HTML_files.rb +3 -0
  27. data/sample/Set_iChat_status.rb +3 -0
  28. data/sample/Simple_Finder_GUI_Scripting.rb +6 -3
  29. data/sample/Stagger_Finder_windows.rb +3 -0
  30. data/sample/TextEdit_demo.rb +3 -0
  31. data/sample/iTunes_top40_to_html.rb +3 -0
  32. data/src/SendThreadSafe.c +380 -0
  33. data/src/SendThreadSafe.h +139 -0
  34. data/src/lib/_aem/aemreference.rb +46 -18
  35. data/src/lib/_aem/codecs.rb +19 -3
  36. data/src/lib/_aem/mactypes.rb +2 -6
  37. data/src/lib/_aem/send.rb +1 -1
  38. data/src/lib/_aem/typewrappers.rb +2 -2
  39. data/src/lib/_appscript/referencerenderer.rb +10 -4
  40. data/src/lib/_appscript/reservedkeywords.rb +4 -4
  41. data/src/lib/_appscript/terminology.rb +43 -35
  42. data/src/lib/aem.rb +8 -4
  43. data/src/lib/appscript.rb +78 -15
  44. data/src/lib/kae.rb +4 -0
  45. data/src/lib/osax.rb +9 -6
  46. data/src/rbae.c +102 -23
  47. data/test/test_aemreference.rb +4 -4
  48. data/test/test_appscriptcommands.rb +2 -2
  49. data/test/test_appscriptreference.rb +4 -4
  50. data/test/test_codecs.rb +14 -1
  51. data/test/test_findapp.rb +1 -1
  52. data/test/test_mactypes.rb +1 -1
  53. data/test/test_osax.rb +1 -1
  54. data/test/testall.sh +1 -1
  55. 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
- "does_not_start_with",
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
- @_str = aete.data
208
- @_ptr = 6 # version, language, script integers
209
- _integer.times { parse_suite }
210
- if not @_ptr == @_str.length
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
- classes, enums, properties, elements, commands = TerminologyParser.build_tables_for_aetes(aetes.delete_if { |aete| not (aete.is_a?(AE::AEDesc) and aete.type == KAE::TypeAETE) })
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
- begin
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
- # Write module
379
- File.open(out_path, "w") do |f|
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 AE::MacOSError => e
384
- if e.to_i == -192 # aete resource not found
385
- raise RuntimeError, "No terminology found."
386
- else
387
- raise
388
- end
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
- aetes.delete_if { |aete| not (aete.is_a?(AE::AEDesc) and aete.type == KAE::TypeAETE) }
391
- # Parse aete(s) into intermediate tables, suitable for use by Terminology#tables_for_module
392
- tables = TerminologyParser.build_tables_for_aetes(aetes)
393
- # Write module code
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 'AEM::Application.current'
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 "AEM::Application.#{con_name}(#{@identity[1].inspect})"
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 start_transaction(session=nil)
184
- # Start a new transaction.
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
- new_ref = @AS_aem_reference.by_index(selector)
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 start
572
- return Reference.new(@AS_app_data, @AS_aem_reference.start)
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 starts_with(operand)
629
- return Reference.new(@AS_app_data, @AS_aem_reference.starts_with(operand))
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 does_not_start_with(operand)
645
- return self.starts_with(operand).not
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
- else
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 start_transaction(session=nil)
731
- @AS_app_data.target.start_transaction(session)
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
@@ -1481,4 +1481,8 @@ module KAE
1481
1481
  TypeWhoseRange = 'wrng'
1482
1482
  TypeWildCard = '****'
1483
1483
  TypeYards = 'yard'
1484
+
1485
+ # new in 10.5
1486
+ TypeUInt16 = 'ushr'
1487
+ TypeUInt64 = 'ucom'
1484
1488
  end
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
- @_terms = terms
136
- else
137
- desc = AE.get_app_terminology(path).coerce(KAE::TypeAEList)
138
- @_terms = OSAXCache[osax_name][1] = \
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: FUJIMOTO Hisakuni, author of RubyAEOSA
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
- typedef long refcontype;
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 %i>", NUM2INT(rb_iv_get(self, "@number")));
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
- rbStringToDescType(key),
332
- rbStringToDescType(type),
333
- &desc);
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
- rbStringToDescType(key),
347
- rbStringToDescType(type),
348
- &desc);
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
- FSSpec fss;
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
- err = FSGetCatalogInfo(&appRef, kFSCatInfoNone, NULL, NULL, &fss, NULL);
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, &paraDesc);
460
517
  paraSize = AEGetDescDataSize(&paraDesc);
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
- launchParams.launchAppSpec = &fss;
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, refcontype refcon)
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, VALUE handler)
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, (long)handler,
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
- VALUE handler;
666
+ SRefCon handler;
599
667
 
600
668
  err = AEGetEventHandler(rbStringToDescType(eventClass),
601
669
  rbStringToDescType(eventID),
602
- &handlerUPP, (long *)&handler,
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, refcontype refcon, AEDesc *toDesc)
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, VALUE handler)
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, (long)handler,
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
- VALUE handler;
744
+ SRefCon handler;
677
745
  Boolean fromTypeIsDesc;
678
746
 
679
747
  err = AEGetCoercionHandler(rbStringToDescType(fromType),
680
748
  rbStringToDescType(toType),
681
- &handlerUPP, (long *)&handler,
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