s0nspark-rubyosa 0.5.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.
@@ -0,0 +1,141 @@
1
+ # Copyright (c) 2006-2007, Apple Inc. All rights reserved.
2
+ #
3
+ # Redistribution and use in source and binary forms, with or without
4
+ # modification, are permitted provided that the following conditions
5
+ # are met:
6
+ # 1. Redistributions of source code must retain the above copyright
7
+ # notice, this list of conditions and the following disclaimer.
8
+ # 2. Redistributions in binary form must reproduce the above copyright
9
+ # notice, this list of conditions and the following disclaimer in the
10
+ # documentation and/or other materials provided with the distribution.
11
+ # 3. Neither the name of Apple Inc. ("Apple") nor the names of
12
+ # its contributors may be used to endorse or promote products derived
13
+ # from this software without specific prior written permission.
14
+ #
15
+ # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
16
+ # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ # ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
19
+ # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
+ # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
+ # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24
+ # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25
+ # POSSIBILITY OF SUCH DAMAGE.
26
+
27
+ require 'enumerator'
28
+
29
+ module OSA
30
+ @sym_to_code = {}
31
+ @code_to_sym = {}
32
+
33
+ def self.add_property(sym, code, override=false)
34
+ unless override
35
+ return if @sym_to_code.has_key?(sym) or @code_to_sym.has_key?(code)
36
+ end
37
+ @sym_to_code[sym] = code
38
+ @code_to_sym[code] = sym
39
+ end
40
+
41
+ def self.sym_to_code(sym)
42
+ @sym_to_code[sym]
43
+ end
44
+
45
+ def self.code_to_sym(code)
46
+ @code_to_sym[code]
47
+ end
48
+ end
49
+
50
+ [
51
+ # pArcAngle
52
+ :arc_angle, 'parc',
53
+ :background_color, 'pbcl',
54
+ :background_pattern, 'pbpt',
55
+ :best_type, 'pbst',
56
+ :bounds, 'pbnd',
57
+ :class, 'pcls',
58
+ :clipboard, 'pcli',
59
+ :color, 'colr',
60
+ :color_table, 'cltb',
61
+ :contents, 'pcnt',
62
+ :corner_curve_height, 'pchd',
63
+ :corner_curve_width, 'pcwd',
64
+ :dash_style, 'pdst',
65
+ :default_type, 'deft',
66
+ :definition_rect, 'pdrt',
67
+ :enabled, 'enbl',
68
+ :end_point, 'pend',
69
+ :fill_color, 'flcl',
70
+ :fill_pattern, 'flpt',
71
+ :font, 'font',
72
+
73
+ # pFormula
74
+ :formula, 'pfor',
75
+ :graphic_objects, 'gobs',
76
+ :has_close_box, 'hclb',
77
+ :has_title_bar, 'ptit',
78
+ :id, 'ID ',
79
+ :index, 'pidx',
80
+ :insertion_loc, 'pins',
81
+ :is_floating, 'isfl',
82
+ :is_front_process, 'pisf',
83
+ :is_modal, 'pmod',
84
+ :is_modified, 'imod',
85
+ :is_resizable, 'prsz',
86
+ :is_stationery_pad, 'pspd',
87
+ :is_zoomable, 'iszm',
88
+ :is_zoomed, 'pzum',
89
+ :item_number, 'itmn',
90
+ :justification, 'pjst',
91
+ :line_arrow, 'arro',
92
+ :menu_id, 'mnid',
93
+ :name, 'pnam',
94
+
95
+ # pNewElementLoc
96
+ :new_element_loc, 'pnel',
97
+ :pen_color, 'ppcl',
98
+ :pen_pattern, 'pppa',
99
+ :pen_width, 'ppwd',
100
+ :pixel_depth, 'pdpt',
101
+ :point_list, 'ptlt',
102
+ :point_size, 'ptsz',
103
+ :protection, 'ppro',
104
+ :rotation, 'prot',
105
+ :scale, 'pscl',
106
+ :script, 'scpt',
107
+ :script_tag, 'psct',
108
+ :selected, 'selc',
109
+ :selection, 'sele',
110
+ :start_angle, 'pang',
111
+ :start_point, 'pstp',
112
+ :text_color, 'ptxc',
113
+ :text_font, 'ptxf',
114
+ :text_item_delimiters, 'txdl',
115
+ :text_point_size, 'ptps',
116
+
117
+ # pScheme
118
+ :scheme, 'pusc',
119
+ :host, 'HOST',
120
+ :path, 'FTPc',
121
+ :user_name, 'RAun',
122
+ :user_password, 'RApw',
123
+ :dns_form, 'pDNS',
124
+ :url, 'pURL',
125
+ :text_encoding, 'ptxe',
126
+ :ftp_kind, 'kind',
127
+
128
+ # pTextStyles
129
+ :text_styles, 'txst',
130
+ :transfer_mode, 'pptm',
131
+ :translation, 'ptrs',
132
+ :uniform_styles, 'ustl',
133
+ :update_on, 'pupd',
134
+ :user_selection, 'pusl',
135
+ :version, 'vers',
136
+ :visible, 'pvis'
137
+
138
+ ].each_slice(2) { |sym, code| OSA.add_property(sym, code) }
139
+
140
+ # A convenience shortcut to :point_size
141
+ OSA.add_property(:size, 'ptsz', true)
data/src/rbosa.c ADDED
@@ -0,0 +1,720 @@
1
+ /*
2
+ * Copyright (c) 2006-2007, Apple Inc. All rights reserved.
3
+ *
4
+ * Redistribution and use in source and binary forms, with or without
5
+ * modification, are permitted provided that the following conditions
6
+ * are met:
7
+ * 1. Redistributions of source code must retain the above copyright
8
+ * notice, this list of conditions and the following disclaimer.
9
+ * 2. Redistributions in binary form must reproduce the above copyright
10
+ * notice, this list of conditions and the following disclaimer in the
11
+ * documentation and/or other materials provided with the distribution.
12
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
13
+ * its contributors may be used to endorse or promote products derived
14
+ * from this software without specific prior written permission.
15
+ *
16
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
17
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
20
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ * POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+ #include "rbosa.h"
30
+ #include <st.h>
31
+
32
+ static VALUE mOSA;
33
+ static VALUE cOSAElement;
34
+ static VALUE cOSAElementList;
35
+ static VALUE cOSAElementRecord;
36
+ static VALUE mOSAEventDispatcher;
37
+
38
+ static ID sClasses;
39
+ static ID sApp;
40
+
41
+ static void
42
+ rbosa_element_free (void *ptr)
43
+ {
44
+ AEDisposeDesc (ptr);
45
+ free (ptr);
46
+ }
47
+
48
+ static VALUE
49
+ __rbosa_class_from_desc_data (VALUE app, AEDesc res)
50
+ {
51
+ DescType data;
52
+ Size datasize;
53
+ VALUE classes, klass;
54
+
55
+ classes = rb_ivar_get (app, sClasses);
56
+ if (NIL_P (classes))
57
+ return Qnil;
58
+ klass = Qnil;
59
+
60
+ datasize = AEGetDescDataSize (&res);
61
+ /* This should always be a four-byte code. */
62
+ if (datasize != sizeof (DescType))
63
+ return Qnil;
64
+
65
+ if (AEGetDescData (&res, &data, datasize) == noErr) {
66
+ char dtStr[5];
67
+
68
+ *(DescType *)dtStr = CFSwapInt32HostToBig (data);
69
+ klass = rb_hash_aref (classes, rb_str_new (dtStr, 4));
70
+ }
71
+
72
+ return klass;
73
+ }
74
+
75
+ static VALUE
76
+ rbosa_element_make (VALUE klass, AEDesc *desc, VALUE app)
77
+ {
78
+ AEDesc * newDesc;
79
+ VALUE new_klass, obj;
80
+
81
+ newDesc = (AEDesc *)malloc (sizeof (AEDesc));
82
+ if (newDesc == NULL)
83
+ rb_fatal ("cannot allocate memory");
84
+ memcpy (newDesc, desc, sizeof (AEDesc));
85
+ new_klass = Qnil;
86
+
87
+ /* Let's replace the klass here according to the type of the descriptor,
88
+ * if the basic class OSA::Element was given.
89
+ */
90
+ if (klass == cOSAElement) {
91
+ if (newDesc->descriptorType == 'list') {
92
+ klass = cOSAElementList;
93
+ }
94
+ else if (newDesc->descriptorType == 'reco') {
95
+ klass = cOSAElementRecord;
96
+ }
97
+ else if (newDesc->descriptorType == 'type') {
98
+ new_klass = __rbosa_class_from_desc_data (app, *newDesc);
99
+ }
100
+ else if (newDesc->descriptorType == 'obj ' && !NIL_P (app)) {
101
+ AEDesc res;
102
+ OSErr err;
103
+
104
+ if ((err = AEGetParamDesc ((AppleEvent *)newDesc, 'want', '****', &res)) == noErr)
105
+ new_klass = __rbosa_class_from_desc_data (app, res);
106
+ }
107
+ }
108
+
109
+ if (!NIL_P (new_klass))
110
+ klass = new_klass;
111
+
112
+ obj = Data_Wrap_Struct (klass, NULL, rbosa_element_free, newDesc);
113
+
114
+ rb_ivar_set (obj, sApp, NIL_P (app) ? obj : app);
115
+
116
+ return obj;
117
+ }
118
+
119
+ static AEDesc *
120
+ rbosa_element_aedesc (VALUE element)
121
+ {
122
+ AEDesc * desc;
123
+
124
+ if (!rb_obj_is_kind_of (element, cOSAElement))
125
+ rb_raise (rb_eArgError, "Invalid argument of type '%s' (required: OSA::Element)", rb_class2name (rb_class_of (element)));
126
+
127
+ Data_Get_Struct (element, AEDesc, desc);
128
+
129
+ return desc;
130
+ }
131
+
132
+ static VALUE
133
+ rbosa_element_new (VALUE self, VALUE type, VALUE value)
134
+ {
135
+ FourCharCode ffc_type;
136
+ OSErr error;
137
+ const char * c_value;
138
+ unsigned c_value_size;
139
+ AEDesc desc;
140
+
141
+ ffc_type = RVAL2FOURCHAR (type);
142
+
143
+ if (NIL_P (value)) {
144
+ c_value = NULL;
145
+ c_value_size = 0;
146
+ }
147
+ else if (rb_obj_is_kind_of (value, rb_cInteger)) {
148
+ FourCharCode code;
149
+
150
+ code = NUM2INT (value);
151
+ c_value = (const char *)&code;
152
+ c_value_size = sizeof (FourCharCode);
153
+ }
154
+ else if (ffc_type == 'alis') {
155
+ AliasHandle alias;
156
+
157
+ rbobj_to_alias_handle (value, &alias);
158
+
159
+ c_value = (const char *)*alias;
160
+ c_value_size = GetHandleSize ((Handle)alias);
161
+ }
162
+ else {
163
+ Check_Type (value, T_STRING);
164
+ c_value = RSTRING (value)->ptr;
165
+ c_value_size = RSTRING (value)->len;
166
+ }
167
+
168
+ error = AECreateDesc (ffc_type, c_value, c_value_size, &desc);
169
+ if (error != noErr)
170
+ rb_raise (rb_eArgError, "Cannot create Apple Event descriptor from type '%s' value '%s' : %s (%d)",
171
+ RVAL2CSTR (type), c_value, error_code_to_string (error), error);
172
+
173
+ return rbosa_element_make (self, &desc, Qnil);
174
+ }
175
+
176
+ static VALUE
177
+ rbosa_element_new_os (VALUE self, VALUE desired_class, VALUE container, VALUE key_form, VALUE key_data)
178
+ {
179
+ OSErr error;
180
+ AEDesc obj_specifier;
181
+
182
+ error = CreateObjSpecifier (RVAL2FOURCHAR (desired_class),
183
+ rbosa_element_aedesc (container),
184
+ RVAL2FOURCHAR (key_form),
185
+ rbosa_element_aedesc (key_data),
186
+ false,
187
+ &obj_specifier);
188
+
189
+ if (error != noErr)
190
+ rb_raise (rb_eArgError, "Cannot create Apple Event object specifier for desired class '%s' : %s (%d)",
191
+ RVAL2CSTR (desired_class), error_code_to_string (error), error);
192
+
193
+ return rbosa_element_make (self, &obj_specifier, Qnil);
194
+ }
195
+
196
+ static VALUE
197
+ rbosa_element_dup (VALUE self, VALUE element)
198
+ {
199
+ AEDesc * desc;
200
+ AEDesc new_desc;
201
+ OSErr error;
202
+
203
+ desc = rbosa_element_aedesc (element);
204
+ error = AEDuplicateDesc (desc, &new_desc);
205
+ if (error != noErr)
206
+ rb_raise (rb_eArgError, "Cannot duplicate element : %s (%d)",
207
+ error_code_to_string (error), error);
208
+
209
+ return rbosa_element_make (self, &new_desc, Qnil);
210
+ }
211
+
212
+ static void
213
+ __rbosa_raise_potential_app_error (AEDesc *reply)
214
+ {
215
+ OSErr error;
216
+ AEDesc errorNumDesc;
217
+ AEDesc errorStringDesc;
218
+ int errorNum;
219
+ const char * errorMsg;
220
+ char exception[128];
221
+
222
+ if (AEGetParamDesc (reply, keyErrorNumber, typeSInt32, &errorNumDesc) != noErr)
223
+ return;
224
+
225
+ if (AEGetDescData (&errorNumDesc, &errorNum, sizeof errorNum) != noErr) {
226
+ AEDisposeDesc (&errorNumDesc);
227
+ return;
228
+ }
229
+
230
+ if (errorNum == noErr)
231
+ return;
232
+
233
+ /* The reply is an application error. */
234
+
235
+ errorMsg = error_code_to_string(errorNum);
236
+ if (errorMsg == NULL)
237
+ errorMsg = "Unknown error";
238
+
239
+ exception[0] = '\0';
240
+ error = AEGetParamDesc (reply, keyErrorString, typeChar, &errorStringDesc);
241
+ if (error == noErr) {
242
+ Size size;
243
+
244
+ size = AEGetDescDataSize (&errorStringDesc);
245
+ if (size > 0) {
246
+ char *msg;
247
+
248
+ msg = (char *)malloc (size + 1);
249
+ if (msg != NULL) {
250
+ if (AEGetDescData (&errorStringDesc, msg, size) == noErr) {
251
+ msg[size] = '\0';
252
+ snprintf (exception, sizeof exception, "application returned error: %s (%d), with message: %s", errorMsg, errorNum, msg);
253
+ }
254
+ free (msg);
255
+ }
256
+ }
257
+ AEDisposeDesc (&errorStringDesc);
258
+ }
259
+
260
+ if (exception[0] == '\0')
261
+ snprintf (exception, sizeof exception, "application returned error: %s (%d)", errorMsg, errorNum);
262
+
263
+ AEDisposeDesc (&errorNumDesc);
264
+
265
+ rb_raise (rb_eRuntimeError, exception);
266
+ }
267
+
268
+ static VALUE
269
+ rbosa_app_send_event (VALUE self, VALUE event_class, VALUE event_id, VALUE params, VALUE need_retval)
270
+ {
271
+ OSErr error;
272
+ AppleEvent ae;
273
+ AppleEvent reply;
274
+ VALUE rb_timeout;
275
+ SInt32 timeout;
276
+ VALUE rb_reply;
277
+ unsigned has_direct_param;
278
+
279
+ error = AECreateAppleEvent (RVAL2FOURCHAR (event_class),
280
+ RVAL2FOURCHAR (event_id),
281
+ rbosa_element_aedesc (self),
282
+ kAutoGenerateReturnID,
283
+ kAnyTransactionID,
284
+ &ae);
285
+ if (error != noErr)
286
+ rb_raise (rb_eArgError, "Cannot create Apple Event '%s%s' : %s (%d)",
287
+ RVAL2CSTR (event_class), RVAL2CSTR (event_id), error_code_to_string (error), error);
288
+
289
+ has_direct_param = 0;
290
+ if (!NIL_P (params)) {
291
+ unsigned i;
292
+
293
+ for (i = 0; i < RARRAY (params)->len; i++) {
294
+ VALUE ary;
295
+ VALUE type;
296
+ VALUE element;
297
+ FourCharCode code;
298
+
299
+ ary = RARRAY (params)->ptr[i];
300
+ if (NIL_P (ary) || RARRAY (ary)->len != 2)
301
+ continue;
302
+
303
+ type = RARRAY (ary)->ptr[0];
304
+ element = RARRAY (ary)->ptr[1];
305
+ code = RVAL2FOURCHAR (type);
306
+
307
+ if (code == '----')
308
+ has_direct_param = 1;
309
+
310
+ error = AEPutParamDesc (&ae, RVAL2FOURCHAR (type), rbosa_element_aedesc (element));
311
+ if (error != noErr) {
312
+ AEDisposeDesc (&ae);
313
+ rb_raise (rb_eArgError, "Cannot add Apple Event parameter '%s' : %s (%d)",
314
+ RVAL2CSTR (type), error_code_to_string (error), error);
315
+ }
316
+ }
317
+ }
318
+
319
+ rb_timeout = rb_iv_get (mOSA, "@timeout");
320
+ timeout = NIL_P (rb_timeout) ? kAEDefaultTimeout : NUM2INT (rb_timeout);
321
+
322
+ if (has_direct_param == 0)
323
+ AEPutAttributePtr (&ae, 'subj', typeNull, NULL, 0);
324
+
325
+ error = AESend (&ae, &reply, (RVAL2CBOOL(need_retval) ? kAEWaitReply : kAENoReply) | kAECanInteract | kAECanSwitchLayer,
326
+ kAENormalPriority, timeout, NULL, NULL);
327
+
328
+ AEDisposeDesc (&ae);
329
+
330
+ if (error != noErr)
331
+ rb_raise (rb_eRuntimeError, "Cannot send Apple Event '%s%s' : %s (%d)",
332
+ RVAL2CSTR (event_class), RVAL2CSTR (event_id), error_code_to_string (error), error);
333
+
334
+ __rbosa_raise_potential_app_error (&reply);
335
+
336
+ if (RTEST (need_retval)) {
337
+ AEDesc replyObject;
338
+
339
+ AEGetParamDesc (&reply, keyDirectObject, typeWildCard, &replyObject);
340
+
341
+ rb_reply = rbosa_element_make (cOSAElement, &replyObject, self);
342
+ }
343
+ else {
344
+ rb_reply = Qnil;
345
+ }
346
+
347
+ AEDisposeDesc (&reply);
348
+
349
+ return rb_reply;
350
+ }
351
+
352
+ static VALUE
353
+ rbosa_element_type (VALUE self)
354
+ {
355
+ AEDesc *desc;
356
+ char dtStr[5];
357
+
358
+ desc = rbosa_element_aedesc (self);
359
+ *(DescType*)dtStr = CFSwapInt32HostToBig (desc->descriptorType);
360
+
361
+ return rb_str_new (dtStr, 4);
362
+ }
363
+
364
+ static VALUE
365
+ rbosa_element_data (int argc, VALUE *argv, VALUE self)
366
+ {
367
+ VALUE coerce_type;
368
+ AEDesc coerced_desc;
369
+ AEDesc * desc;
370
+ OSErr error;
371
+ void * data;
372
+ Size datasize;
373
+ VALUE retval;
374
+ bool to_4cc;
375
+
376
+ rb_scan_args (argc, argv, "01", &coerce_type);
377
+ to_4cc = false;
378
+
379
+ desc = rbosa_element_aedesc (self);
380
+
381
+ if (!NIL_P (coerce_type)) {
382
+ FourCharCode code;
383
+
384
+ code = RVAL2FOURCHAR (coerce_type);
385
+ error = AECoerceDesc (desc, code, &coerced_desc);
386
+ if (error != noErr)
387
+ rb_raise (rb_eRuntimeError, "Cannot coerce desc to type %s : %s (%d)",
388
+ RVAL2CSTR (coerce_type), error_code_to_string (error), error);
389
+
390
+ desc = &coerced_desc;
391
+ to_4cc = code == 'type';
392
+ }
393
+
394
+ datasize = AEGetDescDataSize (desc);
395
+ data = (void *)malloc (datasize);
396
+ if (data == NULL)
397
+ rb_fatal ("cannot allocate memory");
398
+
399
+ error = AEGetDescData (desc, data, datasize);
400
+ if (error == noErr) {
401
+ if (to_4cc)
402
+ *(DescType*)data = CFSwapInt32HostToBig (*(DescType*)data);
403
+ retval = rb_str_new (data, datasize);
404
+ }
405
+ else {
406
+ retval = Qnil;
407
+ }
408
+
409
+ if (!NIL_P (coerce_type))
410
+ AEDisposeDesc (&coerced_desc);
411
+ free (data);
412
+
413
+ if (error != noErr)
414
+ rb_raise (rb_eRuntimeError, "Cannot get desc data : %s (%d)",
415
+ error_code_to_string (error), error);
416
+
417
+ return retval;
418
+ }
419
+
420
+ static VALUE
421
+ __rbosa_insertion_loc_new (VALUE rcv, FourCharCode code)
422
+ {
423
+ AEDesc * self_desc;
424
+ AEDesc rec;
425
+ AEDesc pos_desc;
426
+ AEDesc new_desc;
427
+
428
+ self_desc = rbosa_element_aedesc (rcv);
429
+ AECreateList (NULL, 0, true, &rec);
430
+ AEPutParamDesc (&rec, keyAEObject, self_desc);
431
+ AECreateDesc (code, NULL, 0, &pos_desc);
432
+ AEPutParamPtr (&rec, keyAEPosition, typeEnumerated, &pos_desc, 4);
433
+ AECoerceDesc (&rec, typeInsertionLoc, &new_desc);
434
+ AEDisposeDesc (&rec);
435
+
436
+ return rbosa_element_make (cOSAElement, &new_desc, Qnil);
437
+ }
438
+
439
+ static VALUE
440
+ rbosa_element_after (VALUE self)
441
+ {
442
+ return __rbosa_insertion_loc_new (self, kAEAfter);
443
+ }
444
+
445
+ static VALUE
446
+ rbosa_element_before (VALUE self)
447
+ {
448
+ return __rbosa_insertion_loc_new (self, kAEBefore);
449
+ }
450
+
451
+ static VALUE
452
+ rbosa_element_eql (VALUE self, VALUE other)
453
+ {
454
+ AEDesc * self_desc;
455
+ AEDesc * other_desc;
456
+ Size data_size;
457
+ void * self_data;
458
+ void * other_data;
459
+ OSErr error;
460
+ Boolean ok;
461
+
462
+ if (!rb_obj_is_kind_of (other, rb_class_real (rb_class_of (self))))
463
+ return Qfalse;
464
+
465
+ self_desc = rbosa_element_aedesc (self);
466
+ other_desc = rbosa_element_aedesc (other);
467
+
468
+ if (self_desc == other_desc)
469
+ return Qtrue;
470
+
471
+ if (self_desc->descriptorType != other_desc->descriptorType)
472
+ return Qfalse;
473
+
474
+ data_size = AEGetDescDataSize (self_desc);
475
+ if (data_size != AEGetDescDataSize (other_desc))
476
+ return Qfalse;
477
+
478
+ self_data = (void *)malloc (data_size);
479
+ other_data = (void *)malloc (data_size);
480
+ ok = 0;
481
+
482
+ if (self_data == NULL || other_data == NULL)
483
+ rb_fatal ("cannot allocate memory");
484
+
485
+ error = AEGetDescData (self_desc, self_data, data_size);
486
+ if (error != noErr)
487
+ goto bails;
488
+
489
+ error = AEGetDescData (other_desc, other_data, data_size);
490
+ if (error != noErr)
491
+ goto bails;
492
+
493
+ ok = memcmp (self_data, other_data, data_size) == 0;
494
+
495
+ bails:
496
+ free (self_data);
497
+ free (other_data);
498
+
499
+ return CBOOL2RVAL (ok);
500
+ }
501
+
502
+ static VALUE
503
+ rbosa_element_inspect (VALUE self)
504
+ {
505
+ Handle h;
506
+ char buf[1024];
507
+
508
+ if (AEPrintDescToHandle (rbosa_element_aedesc (self), &h) != noErr) {
509
+ snprintf (buf, sizeof buf, "<%s:%p>", rb_obj_classname (self), (void *)self);
510
+ }
511
+ else {
512
+ snprintf (buf, sizeof buf, "<%s:%p desc=\"%s\">", rb_obj_classname (self), (void *)self, *h);
513
+ DisposeHandle (h);
514
+ }
515
+
516
+ return CSTR2RVAL (buf);
517
+ }
518
+
519
+ static long
520
+ __rbosa_elementlist_count (AEDescList *list)
521
+ {
522
+ OSErr error;
523
+ long count;
524
+
525
+ error = AECountItems (list, &count);
526
+ if (error != noErr)
527
+ rb_raise (rb_eRuntimeError, "Cannot count items : %s (%d)",
528
+ error_code_to_string (error), error);
529
+
530
+ return count;
531
+ }
532
+
533
+ static void
534
+ __rbosa_elementlist_add (AEDescList *list, VALUE element, long pos)
535
+ {
536
+ OSErr error;
537
+
538
+ error = AEPutDesc (list, pos, rbosa_element_aedesc (element));
539
+ if (error != noErr)
540
+ rb_raise (rb_eRuntimeError, "Cannot add given descriptor : %s (%d)",
541
+ error_code_to_string (error), error);
542
+ }
543
+
544
+ static VALUE
545
+ rbosa_elementlist_new (int argc, VALUE *argv, VALUE self)
546
+ {
547
+ OSErr error;
548
+ AEDescList list;
549
+ VALUE ary;
550
+ int i;
551
+
552
+ rb_scan_args (argc, argv, "01", &ary);
553
+
554
+ if (!NIL_P (ary))
555
+ Check_Type (ary, T_ARRAY);
556
+
557
+ error = AECreateList (NULL, 0, false, &list);
558
+ if (error != noErr)
559
+ rb_raise (rb_eRuntimeError, "Cannot create Apple Event descriptor list : %s (%d)",
560
+ error_code_to_string (error), error);
561
+
562
+ if (!NIL_P (ary)) {
563
+ for (i = 0; i < RARRAY (ary)->len; i++)
564
+ __rbosa_elementlist_add (&list, RARRAY (ary)->ptr[i], i + 1);
565
+ }
566
+
567
+ return rbosa_element_make (self, &list, Qnil);
568
+ }
569
+
570
+ static VALUE
571
+ rbosa_elementlist_add (VALUE self, VALUE element)
572
+ {
573
+ AEDescList * list;
574
+
575
+ list = (AEDescList *)rbosa_element_aedesc (self);
576
+ __rbosa_elementlist_add (list, __rbosa_elementlist_count (list) + 1, element);
577
+
578
+ return self;
579
+ }
580
+
581
+ static VALUE
582
+ __rbosa_elementlist_get (VALUE self, long index, AEKeyword *keyword)
583
+ {
584
+ OSErr error;
585
+ AEDesc desc;
586
+
587
+ error = AEGetNthDesc ((AEDescList *)rbosa_element_aedesc (self),
588
+ index + 1,
589
+ typeWildCard,
590
+ keyword,
591
+ &desc);
592
+
593
+ if (error != noErr)
594
+ rb_raise (rb_eRuntimeError, "Cannot get desc at index %d : %s (%d)",
595
+ index, error_code_to_string (error), error);
596
+
597
+ return rbosa_element_make (cOSAElement, &desc, rb_ivar_get (self, sApp));
598
+ }
599
+
600
+ static VALUE
601
+ rbosa_elementlist_get (VALUE self, VALUE index)
602
+ {
603
+ AEKeyword keyword;
604
+ return __rbosa_elementlist_get (self, FIX2INT (index), &keyword);
605
+ }
606
+
607
+ static VALUE
608
+ rbosa_elementlist_size (VALUE self)
609
+ {
610
+ return INT2FIX (__rbosa_elementlist_count ((AEDescList *)rbosa_element_aedesc (self)));
611
+ }
612
+
613
+ static int
614
+ __rbosa_elementrecord_set (VALUE key, VALUE value, AEDescList *list)
615
+ {
616
+ OSErr error;
617
+
618
+ error = AEPutKeyDesc (list, RVAL2FOURCHAR (key), rbosa_element_aedesc (value));
619
+ if (error != noErr)
620
+ rb_raise (rb_eRuntimeError, "Cannot set value %p for key %p of record %p: %s (%d)",
621
+ value, key, list, error_code_to_string (error), error);
622
+
623
+ return ST_CONTINUE;
624
+ }
625
+
626
+ static VALUE
627
+ rbosa_elementrecord_new (int argc, VALUE *argv, VALUE self)
628
+ {
629
+ OSErr error;
630
+ AEDescList list;
631
+ VALUE hash;
632
+
633
+ rb_scan_args (argc, argv, "01", &hash);
634
+
635
+ if (!NIL_P (hash))
636
+ Check_Type (hash, T_HASH);
637
+
638
+ error = AECreateList (NULL, 0, true, &list);
639
+ if (error != noErr)
640
+ rb_raise (rb_eRuntimeError, "Cannot create Apple Event descriptor list : %s (%d)",
641
+ error_code_to_string (error), error);
642
+
643
+ if (!NIL_P (hash))
644
+ rb_hash_foreach (hash, __rbosa_elementrecord_set, (VALUE)&list);
645
+
646
+ return rbosa_element_make (self, &list, Qnil);
647
+ }
648
+
649
+ static VALUE
650
+ rbosa_elementrecord_to_a (VALUE self)
651
+ {
652
+ long i, count;
653
+ VALUE ary;
654
+
655
+ count = FIX2INT (rbosa_elementlist_size (self));
656
+ ary = rb_ary_new ();
657
+ for (i = 0; i < count; i++) {
658
+ AEKeyword keyword;
659
+ char keyStr[5];
660
+ VALUE val;
661
+
662
+ val = __rbosa_elementlist_get (self, i, &keyword);
663
+ *(AEKeyword *)keyStr = CFSwapInt32HostToBig (keyword);
664
+ keyStr[4] = '\0';
665
+ rb_ary_push (ary, rb_ary_new3 (2, CSTR2RVAL (keyStr), val));
666
+ }
667
+
668
+ return ary;
669
+ }
670
+
671
+ #define rbosa_define_param(name,default_value) \
672
+ do { \
673
+ rb_define_attr (CLASS_OF (mOSA), name, 1, 1); \
674
+ if (default_value == Qtrue || default_value == Qfalse) \
675
+ rb_define_alias (CLASS_OF (mOSA), name"?", name); \
676
+ rb_iv_set (mOSA, "@"name, default_value); \
677
+ } \
678
+ while (0)
679
+
680
+ void
681
+ Init_osa (void)
682
+ {
683
+ sClasses = rb_intern ("@classes");
684
+ sApp = rb_intern ("@app");
685
+
686
+ mOSA = rb_define_module ("OSA");
687
+ rb_define_module_function (mOSA, "__scripting_info__", rbosa_scripting_info, 1);
688
+ rb_define_module_function (mOSA, "__remote_processes__", rbosa_remote_processes, 1);
689
+ rb_define_module_function (mOSA, "__four_char_code__", rbosa_four_char_code, 1);
690
+
691
+ cOSAElement = rb_define_class_under (mOSA, "Element", rb_cObject);
692
+ rb_define_singleton_method (cOSAElement, "__new__", rbosa_element_new, 2);
693
+ rb_define_singleton_method (cOSAElement, "__new_object_specifier__", rbosa_element_new_os, 4);
694
+ rb_define_singleton_method (cOSAElement, "__duplicate__", rbosa_element_dup, 1);
695
+ rb_define_method (cOSAElement, "__type__", rbosa_element_type, 0);
696
+ rb_define_method (cOSAElement, "__data__", rbosa_element_data, -1);
697
+ rb_define_method (cOSAElement, "before", rbosa_element_before, 0);
698
+ rb_define_method (cOSAElement, "after", rbosa_element_after, 0);
699
+ rb_define_method (cOSAElement, "==", rbosa_element_eql, 1);
700
+ rb_define_method (cOSAElement, "inspect", rbosa_element_inspect, 0);
701
+
702
+ cOSAElementList = rb_define_class_under (mOSA, "ElementList", cOSAElement);
703
+ rb_define_singleton_method (cOSAElementList, "__new__", rbosa_elementlist_new, -1);
704
+ rb_define_method (cOSAElementList, "[]", rbosa_elementlist_get, 1);
705
+ rb_define_method (cOSAElementList, "size", rbosa_elementlist_size, 0);
706
+ rb_define_alias (cOSAElementList, "length", "size");
707
+ rb_define_method (cOSAElementList, "add", rbosa_elementlist_add, 1);
708
+
709
+ cOSAElementRecord = rb_define_class_under (mOSA, "ElementRecord", cOSAElement);
710
+ rb_define_singleton_method (cOSAElementRecord, "__new__", rbosa_elementrecord_new, -1);
711
+ rb_define_method (cOSAElementRecord, "to_a", rbosa_elementrecord_to_a, 0);
712
+
713
+ mOSAEventDispatcher = rb_define_module_under (mOSA, "EventDispatcher");
714
+ rb_define_method (mOSAEventDispatcher, "__send_event__", rbosa_app_send_event, 4);
715
+
716
+ rbosa_define_param ("timeout", INT2NUM (kAEDefaultTimeout));
717
+ rbosa_define_param ("lazy_events", Qtrue);
718
+ rbosa_define_param ("utf8_strings", Qfalse);
719
+ rbosa_define_param ("wait_reply", Qnil);
720
+ }