s0nspark-rubyosa 0.5.2

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