dramsay-rubyosa 0.4.0

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)
@@ -0,0 +1,717 @@
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
+ /* The reply is an application error. */
231
+
232
+ errorMsg = error_code_to_string(errorNum);
233
+ if (errorMsg == NULL)
234
+ errorMsg = "Unknown error";
235
+
236
+ exception[0] = '\0';
237
+ error = AEGetParamDesc (reply, keyErrorString, typeChar, &errorStringDesc);
238
+ if (error == noErr) {
239
+ Size size;
240
+
241
+ size = AEGetDescDataSize (&errorStringDesc);
242
+ if (size > 0) {
243
+ char *msg;
244
+
245
+ msg = (char *)malloc (size + 1);
246
+ if (msg != NULL) {
247
+ if (AEGetDescData (&errorStringDesc, msg, size) == noErr) {
248
+ msg[size] = '\0';
249
+ snprintf (exception, sizeof exception, "application returned error: %s (%d), with message: %s", errorMsg, errorNum, msg);
250
+ }
251
+ free (msg);
252
+ }
253
+ }
254
+ AEDisposeDesc (&errorStringDesc);
255
+ }
256
+
257
+ if (exception[0] == '\0')
258
+ snprintf (exception, sizeof exception, "application returned error: %s (%d)", errorMsg, errorNum);
259
+
260
+ AEDisposeDesc (&errorNumDesc);
261
+
262
+ rb_raise (rb_eRuntimeError, exception);
263
+ }
264
+
265
+ static VALUE
266
+ rbosa_app_send_event (VALUE self, VALUE event_class, VALUE event_id, VALUE params, VALUE need_retval)
267
+ {
268
+ OSErr error;
269
+ AppleEvent ae;
270
+ AppleEvent reply;
271
+ VALUE rb_timeout;
272
+ SInt32 timeout;
273
+ VALUE rb_reply;
274
+ unsigned has_direct_param;
275
+
276
+ error = AECreateAppleEvent (RVAL2FOURCHAR (event_class),
277
+ RVAL2FOURCHAR (event_id),
278
+ rbosa_element_aedesc (self),
279
+ kAutoGenerateReturnID,
280
+ kAnyTransactionID,
281
+ &ae);
282
+ if (error != noErr)
283
+ rb_raise (rb_eArgError, "Cannot create Apple Event '%s%s' : %s (%d)",
284
+ RVAL2CSTR (event_class), RVAL2CSTR (event_id), error_code_to_string (error), error);
285
+
286
+ has_direct_param = 0;
287
+ if (!NIL_P (params)) {
288
+ unsigned i;
289
+
290
+ for (i = 0; i < RARRAY (params)->len; i++) {
291
+ VALUE ary;
292
+ VALUE type;
293
+ VALUE element;
294
+ FourCharCode code;
295
+
296
+ ary = RARRAY (params)->ptr[i];
297
+ if (NIL_P (ary) || RARRAY (ary)->len != 2)
298
+ continue;
299
+
300
+ type = RARRAY (ary)->ptr[0];
301
+ element = RARRAY (ary)->ptr[1];
302
+ code = RVAL2FOURCHAR (type);
303
+
304
+ if (code == '----')
305
+ has_direct_param = 1;
306
+
307
+ error = AEPutParamDesc (&ae, RVAL2FOURCHAR (type), rbosa_element_aedesc (element));
308
+ if (error != noErr) {
309
+ AEDisposeDesc (&ae);
310
+ rb_raise (rb_eArgError, "Cannot add Apple Event parameter '%s' : %s (%d)",
311
+ RVAL2CSTR (type), error_code_to_string (error), error);
312
+ }
313
+ }
314
+ }
315
+
316
+ rb_timeout = rb_iv_get (mOSA, "@timeout");
317
+ timeout = NIL_P (rb_timeout) ? kAEDefaultTimeout : NUM2INT (rb_timeout);
318
+
319
+ if (has_direct_param == 0)
320
+ AEPutAttributePtr (&ae, 'subj', typeNull, NULL, 0);
321
+
322
+ error = AESend (&ae, &reply, (RVAL2CBOOL(need_retval) ? kAEWaitReply : kAENoReply) | kAECanInteract | kAECanSwitchLayer,
323
+ kAENormalPriority, timeout, NULL, NULL);
324
+
325
+ AEDisposeDesc (&ae);
326
+
327
+ if (error != noErr)
328
+ rb_raise (rb_eRuntimeError, "Cannot send Apple Event '%s%s' : %s (%d)",
329
+ RVAL2CSTR (event_class), RVAL2CSTR (event_id), error_code_to_string (error), error);
330
+
331
+ __rbosa_raise_potential_app_error (&reply);
332
+
333
+ if (RTEST (need_retval)) {
334
+ AEDesc replyObject;
335
+
336
+ AEGetParamDesc (&reply, keyDirectObject, typeWildCard, &replyObject);
337
+
338
+ rb_reply = rbosa_element_make (cOSAElement, &replyObject, self);
339
+ }
340
+ else {
341
+ rb_reply = Qnil;
342
+ }
343
+
344
+ AEDisposeDesc (&reply);
345
+
346
+ return rb_reply;
347
+ }
348
+
349
+ static VALUE
350
+ rbosa_element_type (VALUE self)
351
+ {
352
+ AEDesc *desc;
353
+ char dtStr[5];
354
+
355
+ desc = rbosa_element_aedesc (self);
356
+ *(DescType*)dtStr = CFSwapInt32HostToBig (desc->descriptorType);
357
+
358
+ return rb_str_new (dtStr, 4);
359
+ }
360
+
361
+ static VALUE
362
+ rbosa_element_data (int argc, VALUE *argv, VALUE self)
363
+ {
364
+ VALUE coerce_type;
365
+ AEDesc coerced_desc;
366
+ AEDesc * desc;
367
+ OSErr error;
368
+ void * data;
369
+ Size datasize;
370
+ VALUE retval;
371
+ bool to_4cc;
372
+
373
+ rb_scan_args (argc, argv, "01", &coerce_type);
374
+ to_4cc = false;
375
+
376
+ desc = rbosa_element_aedesc (self);
377
+
378
+ if (!NIL_P (coerce_type)) {
379
+ FourCharCode code;
380
+
381
+ code = RVAL2FOURCHAR (coerce_type);
382
+ error = AECoerceDesc (desc, code, &coerced_desc);
383
+ if (error != noErr)
384
+ rb_raise (rb_eRuntimeError, "Cannot coerce desc to type %s : %s (%d)",
385
+ RVAL2CSTR (coerce_type), error_code_to_string (error), error);
386
+
387
+ desc = &coerced_desc;
388
+ to_4cc = code == 'type';
389
+ }
390
+
391
+ datasize = AEGetDescDataSize (desc);
392
+ data = (void *)malloc (datasize);
393
+ if (data == NULL)
394
+ rb_fatal ("cannot allocate memory");
395
+
396
+ error = AEGetDescData (desc, data, datasize);
397
+ if (error == noErr) {
398
+ if (to_4cc)
399
+ *(DescType*)data = CFSwapInt32HostToBig (*(DescType*)data);
400
+ retval = rb_str_new (data, datasize);
401
+ }
402
+ else {
403
+ retval = Qnil;
404
+ }
405
+
406
+ if (!NIL_P (coerce_type))
407
+ AEDisposeDesc (&coerced_desc);
408
+ free (data);
409
+
410
+ if (error != noErr)
411
+ rb_raise (rb_eRuntimeError, "Cannot get desc data : %s (%d)",
412
+ error_code_to_string (error), error);
413
+
414
+ return retval;
415
+ }
416
+
417
+ static VALUE
418
+ __rbosa_insertion_loc_new (VALUE rcv, FourCharCode code)
419
+ {
420
+ AEDesc * self_desc;
421
+ AEDesc rec;
422
+ AEDesc pos_desc;
423
+ AEDesc new_desc;
424
+
425
+ self_desc = rbosa_element_aedesc (rcv);
426
+ AECreateList (NULL, 0, true, &rec);
427
+ AEPutParamDesc (&rec, keyAEObject, self_desc);
428
+ AECreateDesc (code, NULL, 0, &pos_desc);
429
+ AEPutParamPtr (&rec, keyAEPosition, typeEnumerated, &pos_desc, 4);
430
+ AECoerceDesc (&rec, typeInsertionLoc, &new_desc);
431
+ AEDisposeDesc (&rec);
432
+
433
+ return rbosa_element_make (cOSAElement, &new_desc, Qnil);
434
+ }
435
+
436
+ static VALUE
437
+ rbosa_element_after (VALUE self)
438
+ {
439
+ return __rbosa_insertion_loc_new (self, kAEAfter);
440
+ }
441
+
442
+ static VALUE
443
+ rbosa_element_before (VALUE self)
444
+ {
445
+ return __rbosa_insertion_loc_new (self, kAEBefore);
446
+ }
447
+
448
+ static VALUE
449
+ rbosa_element_eql (VALUE self, VALUE other)
450
+ {
451
+ AEDesc * self_desc;
452
+ AEDesc * other_desc;
453
+ Size data_size;
454
+ void * self_data;
455
+ void * other_data;
456
+ OSErr error;
457
+ Boolean ok;
458
+
459
+ if (!rb_obj_is_kind_of (other, rb_class_real (rb_class_of (self))))
460
+ return Qfalse;
461
+
462
+ self_desc = rbosa_element_aedesc (self);
463
+ other_desc = rbosa_element_aedesc (other);
464
+
465
+ if (self_desc == other_desc)
466
+ return Qtrue;
467
+
468
+ if (self_desc->descriptorType != other_desc->descriptorType)
469
+ return Qfalse;
470
+
471
+ data_size = AEGetDescDataSize (self_desc);
472
+ if (data_size != AEGetDescDataSize (other_desc))
473
+ return Qfalse;
474
+
475
+ self_data = (void *)malloc (data_size);
476
+ other_data = (void *)malloc (data_size);
477
+ ok = 0;
478
+
479
+ if (self_data == NULL || other_data == NULL)
480
+ rb_fatal ("cannot allocate memory");
481
+
482
+ error = AEGetDescData (self_desc, self_data, data_size);
483
+ if (error != noErr)
484
+ goto bails;
485
+
486
+ error = AEGetDescData (other_desc, other_data, data_size);
487
+ if (error != noErr)
488
+ goto bails;
489
+
490
+ ok = memcmp (self_data, other_data, data_size) == 0;
491
+
492
+ bails:
493
+ free (self_data);
494
+ free (other_data);
495
+
496
+ return CBOOL2RVAL (ok);
497
+ }
498
+
499
+ static VALUE
500
+ rbosa_element_inspect (VALUE self)
501
+ {
502
+ Handle h;
503
+ char buf[1024];
504
+
505
+ if (AEPrintDescToHandle (rbosa_element_aedesc (self), &h) != noErr) {
506
+ snprintf (buf, sizeof buf, "<%s:%p>", rb_obj_classname (self), (void *)self);
507
+ }
508
+ else {
509
+ snprintf (buf, sizeof buf, "<%s:%p desc=\"%s\">", rb_obj_classname (self), (void *)self, *h);
510
+ DisposeHandle (h);
511
+ }
512
+
513
+ return CSTR2RVAL (buf);
514
+ }
515
+
516
+ static long
517
+ __rbosa_elementlist_count (AEDescList *list)
518
+ {
519
+ OSErr error;
520
+ long count;
521
+
522
+ error = AECountItems (list, &count);
523
+ if (error != noErr)
524
+ rb_raise (rb_eRuntimeError, "Cannot count items : %s (%d)",
525
+ error_code_to_string (error), error);
526
+
527
+ return count;
528
+ }
529
+
530
+ static void
531
+ __rbosa_elementlist_add (AEDescList *list, VALUE element, long pos)
532
+ {
533
+ OSErr error;
534
+
535
+ error = AEPutDesc (list, pos, rbosa_element_aedesc (element));
536
+ if (error != noErr)
537
+ rb_raise (rb_eRuntimeError, "Cannot add given descriptor : %s (%d)",
538
+ error_code_to_string (error), error);
539
+ }
540
+
541
+ static VALUE
542
+ rbosa_elementlist_new (int argc, VALUE *argv, VALUE self)
543
+ {
544
+ OSErr error;
545
+ AEDescList list;
546
+ VALUE ary;
547
+ int i;
548
+
549
+ rb_scan_args (argc, argv, "01", &ary);
550
+
551
+ if (!NIL_P (ary))
552
+ Check_Type (ary, T_ARRAY);
553
+
554
+ error = AECreateList (NULL, 0, false, &list);
555
+ if (error != noErr)
556
+ rb_raise (rb_eRuntimeError, "Cannot create Apple Event descriptor list : %s (%d)",
557
+ error_code_to_string (error), error);
558
+
559
+ if (!NIL_P (ary)) {
560
+ for (i = 0; i < RARRAY (ary)->len; i++)
561
+ __rbosa_elementlist_add (&list, RARRAY (ary)->ptr[i], i + 1);
562
+ }
563
+
564
+ return rbosa_element_make (self, &list, Qnil);
565
+ }
566
+
567
+ static VALUE
568
+ rbosa_elementlist_add (VALUE self, VALUE element)
569
+ {
570
+ AEDescList * list;
571
+
572
+ list = (AEDescList *)rbosa_element_aedesc (self);
573
+ __rbosa_elementlist_add (list, __rbosa_elementlist_count (list) + 1, element);
574
+
575
+ return self;
576
+ }
577
+
578
+ static VALUE
579
+ __rbosa_elementlist_get (VALUE self, long index, AEKeyword *keyword)
580
+ {
581
+ OSErr error;
582
+ AEDesc desc;
583
+
584
+ error = AEGetNthDesc ((AEDescList *)rbosa_element_aedesc (self),
585
+ index + 1,
586
+ typeWildCard,
587
+ keyword,
588
+ &desc);
589
+
590
+ if (error != noErr)
591
+ rb_raise (rb_eRuntimeError, "Cannot get desc at index %d : %s (%d)",
592
+ index, error_code_to_string (error), error);
593
+
594
+ return rbosa_element_make (cOSAElement, &desc, rb_ivar_get (self, sApp));
595
+ }
596
+
597
+ static VALUE
598
+ rbosa_elementlist_get (VALUE self, VALUE index)
599
+ {
600
+ AEKeyword keyword;
601
+ return __rbosa_elementlist_get (self, FIX2INT (index), &keyword);
602
+ }
603
+
604
+ static VALUE
605
+ rbosa_elementlist_size (VALUE self)
606
+ {
607
+ return INT2FIX (__rbosa_elementlist_count ((AEDescList *)rbosa_element_aedesc (self)));
608
+ }
609
+
610
+ static int
611
+ __rbosa_elementrecord_set (VALUE key, VALUE value, AEDescList *list)
612
+ {
613
+ OSErr error;
614
+
615
+ error = AEPutKeyDesc (list, RVAL2FOURCHAR (key), rbosa_element_aedesc (value));
616
+ if (error != noErr)
617
+ rb_raise (rb_eRuntimeError, "Cannot set value %p for key %p of record %p: %s (%d)",
618
+ value, key, list, error_code_to_string (error), error);
619
+
620
+ return ST_CONTINUE;
621
+ }
622
+
623
+ static VALUE
624
+ rbosa_elementrecord_new (int argc, VALUE *argv, VALUE self)
625
+ {
626
+ OSErr error;
627
+ AEDescList list;
628
+ VALUE hash;
629
+
630
+ rb_scan_args (argc, argv, "01", &hash);
631
+
632
+ if (!NIL_P (hash))
633
+ Check_Type (hash, T_HASH);
634
+
635
+ error = AECreateList (NULL, 0, true, &list);
636
+ if (error != noErr)
637
+ rb_raise (rb_eRuntimeError, "Cannot create Apple Event descriptor list : %s (%d)",
638
+ error_code_to_string (error), error);
639
+
640
+ if (!NIL_P (hash))
641
+ rb_hash_foreach (hash, __rbosa_elementrecord_set, (VALUE)&list);
642
+
643
+ return rbosa_element_make (self, &list, Qnil);
644
+ }
645
+
646
+ static VALUE
647
+ rbosa_elementrecord_to_a (VALUE self)
648
+ {
649
+ long i, count;
650
+ VALUE ary;
651
+
652
+ count = FIX2INT (rbosa_elementlist_size (self));
653
+ ary = rb_ary_new ();
654
+ for (i = 0; i < count; i++) {
655
+ AEKeyword keyword;
656
+ char keyStr[5];
657
+ VALUE val;
658
+
659
+ val = __rbosa_elementlist_get (self, i, &keyword);
660
+ *(AEKeyword *)keyStr = CFSwapInt32HostToBig (keyword);
661
+ keyStr[4] = '\0';
662
+ rb_ary_push (ary, rb_ary_new3 (2, CSTR2RVAL (keyStr), val));
663
+ }
664
+
665
+ return ary;
666
+ }
667
+
668
+ #define rbosa_define_param(name,default_value) \
669
+ do { \
670
+ rb_define_attr (CLASS_OF (mOSA), name, 1, 1); \
671
+ if (default_value == Qtrue || default_value == Qfalse) \
672
+ rb_define_alias (CLASS_OF (mOSA), name"?", name); \
673
+ rb_iv_set (mOSA, "@"name, default_value); \
674
+ } \
675
+ while (0)
676
+
677
+ void
678
+ Init_osa (void)
679
+ {
680
+ sClasses = rb_intern ("@classes");
681
+ sApp = rb_intern ("@app");
682
+
683
+ mOSA = rb_define_module ("OSA");
684
+ rb_define_module_function (mOSA, "__scripting_info__", rbosa_scripting_info, 1);
685
+ rb_define_module_function (mOSA, "__remote_processes__", rbosa_remote_processes, 1);
686
+ rb_define_module_function (mOSA, "__four_char_code__", rbosa_four_char_code, 1);
687
+
688
+ cOSAElement = rb_define_class_under (mOSA, "Element", rb_cObject);
689
+ rb_define_singleton_method (cOSAElement, "__new__", rbosa_element_new, 2);
690
+ rb_define_singleton_method (cOSAElement, "__new_object_specifier__", rbosa_element_new_os, 4);
691
+ rb_define_singleton_method (cOSAElement, "__duplicate__", rbosa_element_dup, 1);
692
+ rb_define_method (cOSAElement, "__type__", rbosa_element_type, 0);
693
+ rb_define_method (cOSAElement, "__data__", rbosa_element_data, -1);
694
+ rb_define_method (cOSAElement, "before", rbosa_element_before, 0);
695
+ rb_define_method (cOSAElement, "after", rbosa_element_after, 0);
696
+ rb_define_method (cOSAElement, "==", rbosa_element_eql, 1);
697
+ rb_define_method (cOSAElement, "inspect", rbosa_element_inspect, 0);
698
+
699
+ cOSAElementList = rb_define_class_under (mOSA, "ElementList", cOSAElement);
700
+ rb_define_singleton_method (cOSAElementList, "__new__", rbosa_elementlist_new, -1);
701
+ rb_define_method (cOSAElementList, "[]", rbosa_elementlist_get, 1);
702
+ rb_define_method (cOSAElementList, "size", rbosa_elementlist_size, 0);
703
+ rb_define_alias (cOSAElementList, "length", "size");
704
+ rb_define_method (cOSAElementList, "add", rbosa_elementlist_add, 1);
705
+
706
+ cOSAElementRecord = rb_define_class_under (mOSA, "ElementRecord", cOSAElement);
707
+ rb_define_singleton_method (cOSAElementRecord, "__new__", rbosa_elementrecord_new, -1);
708
+ rb_define_method (cOSAElementRecord, "to_a", rbosa_elementrecord_to_a, 0);
709
+
710
+ mOSAEventDispatcher = rb_define_module_under (mOSA, "EventDispatcher");
711
+ rb_define_method (mOSAEventDispatcher, "__send_event__", rbosa_app_send_event, 4);
712
+
713
+ rbosa_define_param ("timeout", INT2NUM (kAEDefaultTimeout));
714
+ rbosa_define_param ("lazy_events", Qtrue);
715
+ rbosa_define_param ("utf8_strings", Qfalse);
716
+ rbosa_define_param ("wait_reply", Qnil);
717
+ }