pasteboard 1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data.tar.gz.sig +3 -0
- data/.autotest +14 -0
- data/.gemtest +0 -0
- data/History.txt +5 -0
- data/Manifest.txt +12 -0
- data/README.rdoc +97 -0
- data/Rakefile +26 -0
- data/ext/pasteboard/extconf.rb +14 -0
- data/ext/pasteboard/pasteboard.c +478 -0
- data/lib/pasteboard.rb +251 -0
- data/lib/pasteboard/type.rb +713 -0
- data/sample/dump.rb +16 -0
- data/sample/image.rb +110 -0
- data/test/test_pasteboard.rb +287 -0
- metadata +151 -0
- metadata.gz.sig +0 -0
data.tar.gz.sig
ADDED
data/.autotest
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'autotest/restart'
|
4
|
+
|
5
|
+
Autotest.add_hook :initialize do |at|
|
6
|
+
at.testlib = 'minitest/autorun'
|
7
|
+
end
|
8
|
+
|
9
|
+
Autotest.add_hook :run_command do |at|
|
10
|
+
at.unit_diff = 'cat'
|
11
|
+
|
12
|
+
system Gem.bin_path('rake', 'rake'), 'compile'
|
13
|
+
end
|
14
|
+
|
data/.gemtest
ADDED
File without changes
|
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
= pasteboard
|
2
|
+
|
3
|
+
* http://github.com/drbrain/pasteboard
|
4
|
+
* http://docs.seattlerb.org/pasteboard
|
5
|
+
|
6
|
+
== DESCRIPTION:
|
7
|
+
|
8
|
+
Pasteboard wraps the OS X system pasteboard. Pasteboard allows you to add
|
9
|
+
and retrieve multiple items and multiple item flavors to the pasteboard unlike
|
10
|
+
+pbpaste+ and +pbcopy+ which only allow text.
|
11
|
+
|
12
|
+
== FEATURES/PROBLEMS:
|
13
|
+
|
14
|
+
* Supports multiple pasteboards
|
15
|
+
* Returns data with the proper encoding
|
16
|
+
* Built in library of types in Pasteboard::Type
|
17
|
+
* Does not understand type conformance (Pasteboard::Type::IMAGE will not
|
18
|
+
retrieve a Pasteboard::Type::JPEG)
|
19
|
+
|
20
|
+
== SYNOPSIS:
|
21
|
+
|
22
|
+
require 'pasteboard'
|
23
|
+
|
24
|
+
pasteboard = Pasteboard.new
|
25
|
+
|
26
|
+
Adding a URL to the clipboard:
|
27
|
+
|
28
|
+
pasteboard.put_url 'http://blog.segment7.net', 'my blog'
|
29
|
+
|
30
|
+
Adding a JPEG with URL to the clipboard:
|
31
|
+
|
32
|
+
pasteboard.put_jpeg_url jpeg, 'http://example', 'my cool jpeg'
|
33
|
+
|
34
|
+
Adding other data to the clipboard (TIFF + URL):
|
35
|
+
|
36
|
+
item = [
|
37
|
+
[Pasteboard::Type::TIFF, tiff],
|
38
|
+
[Pasteboard::Type::URL, url],
|
39
|
+
[Pasteboard::Type::URL_NAME, url],
|
40
|
+
[Pasteboard::Type::UTF_8, url],
|
41
|
+
]
|
42
|
+
|
43
|
+
pasteboard.put item
|
44
|
+
|
45
|
+
Retrieving data from the clipboard:
|
46
|
+
|
47
|
+
require 'pasteboard'
|
48
|
+
|
49
|
+
pb = Pasteboard.new
|
50
|
+
|
51
|
+
pb.first # => all flavors, see Pasteboard#[]
|
52
|
+
|
53
|
+
pb.first Pasteboard::Type::TIFF # => TIFF data
|
54
|
+
|
55
|
+
See also sample/image.rb and sample/dump.rb
|
56
|
+
|
57
|
+
== REQUIREMENTS:
|
58
|
+
|
59
|
+
* OS X
|
60
|
+
|
61
|
+
== INSTALL:
|
62
|
+
|
63
|
+
gem install pasteboard
|
64
|
+
|
65
|
+
== DEVELOPERS:
|
66
|
+
|
67
|
+
After checking out the source, run:
|
68
|
+
|
69
|
+
$ rake newb
|
70
|
+
|
71
|
+
This task will install any missing dependencies, run the tests/specs,
|
72
|
+
and generate the RDoc.
|
73
|
+
|
74
|
+
== LICENSE:
|
75
|
+
|
76
|
+
(The MIT License)
|
77
|
+
|
78
|
+
Copyright (c) 2011 Eric Hodel
|
79
|
+
|
80
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
81
|
+
a copy of this software and associated documentation files (the
|
82
|
+
'Software'), to deal in the Software without restriction, including
|
83
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
84
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
85
|
+
permit persons to whom the Software is furnished to do so, subject to
|
86
|
+
the following conditions:
|
87
|
+
|
88
|
+
The above copyright notice and this permission notice shall be
|
89
|
+
included in all copies or substantial portions of the Software.
|
90
|
+
|
91
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
92
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
93
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
94
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
95
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
96
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
97
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
task :default => :compile
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'hoe'
|
7
|
+
|
8
|
+
Hoe.plugin :minitest
|
9
|
+
Hoe.plugin :git
|
10
|
+
Hoe.plugin :compiler
|
11
|
+
|
12
|
+
Hoe.spec 'pasteboard' do
|
13
|
+
developer 'Eric Hodel', 'drbrain@segment7.net'
|
14
|
+
|
15
|
+
rdoc_locations <<
|
16
|
+
'docs.seattlerb.org:/data/www/docs.seattlerb.org/pasteboard/'
|
17
|
+
|
18
|
+
self.clean_globs = %w[
|
19
|
+
lib/pasteboard/pasteboard.bundle
|
20
|
+
]
|
21
|
+
|
22
|
+
self.spec_extras[:extensions] = %w[ext/pasteboard/extconf.rb]
|
23
|
+
self.readme_file = 'README.rdoc'
|
24
|
+
end
|
25
|
+
|
26
|
+
# vim: syntax=ruby
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
framework_path = '/System/Library/Frameworks/ApplicationServices.framework/Frameworks/HIServices.framework'
|
4
|
+
|
5
|
+
$INCFLAGS << " -I #{File.join framework_path, 'Headers'}"
|
6
|
+
$LDFLAGS << " -framework ApplicationServices"
|
7
|
+
|
8
|
+
abort unless have_header 'Pasteboard.h'
|
9
|
+
|
10
|
+
have_func 'rb_str_encode'
|
11
|
+
|
12
|
+
create_makefile 'pasteboard/pasteboard'
|
13
|
+
create_header
|
14
|
+
|
@@ -0,0 +1,478 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <Pasteboard.h>
|
3
|
+
#include "extconf.h"
|
4
|
+
|
5
|
+
#define BUFSIZE 128
|
6
|
+
|
7
|
+
static VALUE cPB;
|
8
|
+
static VALUE cPBType;
|
9
|
+
static VALUE cPBTypeEncodings;
|
10
|
+
static VALUE ePBError;
|
11
|
+
static VALUE ePBMissing;
|
12
|
+
|
13
|
+
#if HAVE_RB_STR_ENCODE
|
14
|
+
#include <ruby/encoding.h>
|
15
|
+
|
16
|
+
static VALUE BE_BOM;
|
17
|
+
static VALUE LE_BOM;
|
18
|
+
|
19
|
+
static VALUE binary_encoding;
|
20
|
+
static VALUE usascii_encoding;
|
21
|
+
static VALUE utf8_encoding;
|
22
|
+
static VALUE utf16be_encoding;
|
23
|
+
static VALUE utf16le_encoding;
|
24
|
+
static VALUE native_encoding;
|
25
|
+
|
26
|
+
static VALUE utf16_external_flavor;
|
27
|
+
static VALUE utf16_internal_flavor;
|
28
|
+
#endif
|
29
|
+
|
30
|
+
static VALUE
|
31
|
+
string_ref_to_value(CFStringRef ref) {
|
32
|
+
VALUE string = Qnil;
|
33
|
+
char buffer[BUFSIZE];
|
34
|
+
const char * str = NULL;
|
35
|
+
|
36
|
+
str = CFStringGetCStringPtr(ref, kCFStringEncodingUTF8);
|
37
|
+
|
38
|
+
if (str == NULL)
|
39
|
+
if (CFStringGetCString(ref, buffer, BUFSIZE, kCFStringEncodingUTF8))
|
40
|
+
str = buffer;
|
41
|
+
|
42
|
+
if (str == NULL) /* HACK buffer was too small */
|
43
|
+
return Qnil;
|
44
|
+
|
45
|
+
string = rb_str_new2(str);
|
46
|
+
|
47
|
+
#if HAVE_RB_STR_ENCODE
|
48
|
+
rb_enc_associate(string, rb_to_encoding(utf8_encoding));
|
49
|
+
#endif
|
50
|
+
|
51
|
+
return string;
|
52
|
+
}
|
53
|
+
|
54
|
+
static char *
|
55
|
+
value_to_usascii_cstr(VALUE string) {
|
56
|
+
#if HAVE_RB_STR_ENCODE
|
57
|
+
string = rb_str_encode(string, usascii_encoding, 0, Qnil);
|
58
|
+
#endif
|
59
|
+
|
60
|
+
return StringValueCStr(string);
|
61
|
+
}
|
62
|
+
|
63
|
+
static char *
|
64
|
+
value_to_utf8_cstr(VALUE string) {
|
65
|
+
#if HAVE_RB_STR_ENCODE
|
66
|
+
string = rb_str_encode(string, utf8_encoding, 0, Qnil);
|
67
|
+
#endif
|
68
|
+
|
69
|
+
return StringValueCStr(string);
|
70
|
+
}
|
71
|
+
|
72
|
+
#if HAVE_RB_STR_ENCODE
|
73
|
+
static void
|
74
|
+
handle_bom(VALUE data, VALUE default_encoding) {
|
75
|
+
VALUE bom;
|
76
|
+
|
77
|
+
rb_enc_associate(data, rb_to_encoding(binary_encoding));
|
78
|
+
bom = rb_str_substr(data, 0, 2);
|
79
|
+
|
80
|
+
if (rb_str_equal(bom, BE_BOM)) {
|
81
|
+
rb_enc_associate(data, rb_to_encoding(utf16be_encoding));
|
82
|
+
} else if (rb_str_equal(bom, LE_BOM)) {
|
83
|
+
rb_enc_associate(data, rb_to_encoding(utf16le_encoding));
|
84
|
+
} else {
|
85
|
+
rb_enc_associate(data, rb_to_encoding(default_encoding));
|
86
|
+
}
|
87
|
+
}
|
88
|
+
#endif
|
89
|
+
|
90
|
+
static void pb_free(void *ptr) {
|
91
|
+
if (ptr)
|
92
|
+
CFRelease((PasteboardRef)ptr);
|
93
|
+
}
|
94
|
+
|
95
|
+
static VALUE
|
96
|
+
pb_alloc(VALUE klass) {
|
97
|
+
VALUE obj;
|
98
|
+
|
99
|
+
obj = Data_Wrap_Struct(klass, NULL, pb_free, NULL);
|
100
|
+
|
101
|
+
return obj;
|
102
|
+
}
|
103
|
+
|
104
|
+
static void
|
105
|
+
pb_error(OSStatus err) {
|
106
|
+
switch (err) {
|
107
|
+
case noErr:
|
108
|
+
return;
|
109
|
+
case badPasteboardSyncErr:
|
110
|
+
rb_raise(ePBError,
|
111
|
+
"pasteboard has been modified and must be synchronized before use");
|
112
|
+
case badPasteboardIndexErr:
|
113
|
+
rb_raise(ePBMissing, "item does not exist");
|
114
|
+
case badPasteboardItemErr:
|
115
|
+
rb_raise(ePBError, "item reference does not exist");
|
116
|
+
case badPasteboardFlavorErr:
|
117
|
+
rb_raise(ePBError, "item flavor does not exist");
|
118
|
+
case duplicatePasteboardFlavorErr:
|
119
|
+
rb_raise(ePBError, "item flavor already exists");
|
120
|
+
case notPasteboardOwnerErr:
|
121
|
+
rb_raise(ePBError,
|
122
|
+
"pasteboard was not cleared before attempting to add flavor data");
|
123
|
+
case noPasteboardPromiseKeeperErr:
|
124
|
+
rb_raise(ePBError,
|
125
|
+
"promised data added without registering a promise keeper callback");
|
126
|
+
default:
|
127
|
+
rb_raise(ePBError, "unknown");
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
static PasteboardRef
|
132
|
+
pb_get_pasteboard(VALUE obj) {
|
133
|
+
Check_Type(obj, T_DATA);
|
134
|
+
return (PasteboardRef)DATA_PTR(obj);
|
135
|
+
}
|
136
|
+
|
137
|
+
/*
|
138
|
+
* call-seq:
|
139
|
+
* Pasteboard.new type = Pasteboard::CLIPBOARD
|
140
|
+
*
|
141
|
+
* Creates a new pasteboard of the specified +type+.
|
142
|
+
*/
|
143
|
+
static VALUE
|
144
|
+
pb_init(int argc, VALUE* argv, VALUE self) {
|
145
|
+
OSStatus err = noErr;
|
146
|
+
PasteboardRef pasteboard;
|
147
|
+
CFStringRef pasteboard_type = NULL;
|
148
|
+
VALUE type = Qnil;
|
149
|
+
|
150
|
+
if (argc == 0) {
|
151
|
+
pasteboard_type = kPasteboardClipboard;
|
152
|
+
} else {
|
153
|
+
rb_scan_args(argc, argv, "01", &type);
|
154
|
+
}
|
155
|
+
|
156
|
+
if (!NIL_P(type)) {
|
157
|
+
pasteboard_type = CFStringCreateWithCString(NULL,
|
158
|
+
value_to_utf8_cstr(type),
|
159
|
+
kCFStringEncodingUTF8);
|
160
|
+
|
161
|
+
if (pasteboard_type == NULL)
|
162
|
+
rb_raise(ePBError, "unable to allocate memory for pasteboard type");
|
163
|
+
}
|
164
|
+
|
165
|
+
err = PasteboardCreate(pasteboard_type, &pasteboard);
|
166
|
+
|
167
|
+
if (pasteboard_type)
|
168
|
+
CFRelease(pasteboard_type);
|
169
|
+
|
170
|
+
pb_error(err);
|
171
|
+
|
172
|
+
DATA_PTR(self) = (void *)pasteboard;
|
173
|
+
|
174
|
+
return self;
|
175
|
+
}
|
176
|
+
|
177
|
+
/*
|
178
|
+
* call-seq:
|
179
|
+
* pasteboard.clear
|
180
|
+
*
|
181
|
+
* Clears the contents of the pasteboard.
|
182
|
+
*/
|
183
|
+
static VALUE
|
184
|
+
pb_clear(VALUE self) {
|
185
|
+
OSStatus err = noErr;
|
186
|
+
PasteboardRef pasteboard;
|
187
|
+
|
188
|
+
pasteboard = pb_get_pasteboard(self);
|
189
|
+
|
190
|
+
err = PasteboardClear(pasteboard);
|
191
|
+
|
192
|
+
pb_error(err);
|
193
|
+
|
194
|
+
return self;
|
195
|
+
}
|
196
|
+
|
197
|
+
/*
|
198
|
+
* call-seq:
|
199
|
+
* pasteboard.copy_item_flavors identifier
|
200
|
+
*
|
201
|
+
* Returns an Array of flavors for the pasteboard item at +identifier+.
|
202
|
+
*/
|
203
|
+
static VALUE
|
204
|
+
pb_copy_item_flavors(VALUE self, VALUE identifier) {
|
205
|
+
OSStatus err = noErr;
|
206
|
+
PasteboardRef pasteboard;
|
207
|
+
PasteboardItemID item_id;
|
208
|
+
CFArrayRef flavor_types = NULL;
|
209
|
+
CFIndex i, flavor_count = 0;
|
210
|
+
VALUE flavors = Qnil;
|
211
|
+
|
212
|
+
item_id = (PasteboardItemID)NUM2ULONG(identifier);
|
213
|
+
|
214
|
+
pasteboard = pb_get_pasteboard(self);
|
215
|
+
|
216
|
+
err = PasteboardCopyItemFlavors(pasteboard, item_id, &flavor_types);
|
217
|
+
|
218
|
+
pb_error(err);
|
219
|
+
|
220
|
+
flavors = rb_ary_new();
|
221
|
+
|
222
|
+
flavor_count = CFArrayGetCount(flavor_types);
|
223
|
+
|
224
|
+
for (i = 0; i < flavor_count; i++) {
|
225
|
+
CFStringRef flavor_type =
|
226
|
+
(CFStringRef)CFArrayGetValueAtIndex(flavor_types, i);
|
227
|
+
|
228
|
+
rb_ary_push(flavors, string_ref_to_value(flavor_type));
|
229
|
+
}
|
230
|
+
|
231
|
+
CFRelease(flavor_types);
|
232
|
+
|
233
|
+
return flavors;
|
234
|
+
}
|
235
|
+
|
236
|
+
/*
|
237
|
+
* call-seq:
|
238
|
+
* pasteboard.copy_item_flavor_data identifier, flavor
|
239
|
+
*
|
240
|
+
* Retrieves pasteboard data from +identifier+ of +flavor+
|
241
|
+
*/
|
242
|
+
static VALUE
|
243
|
+
pb_copy_item_flavor_data(VALUE self, VALUE identifier, VALUE flavor) {
|
244
|
+
OSStatus err = noErr;
|
245
|
+
PasteboardRef pasteboard;
|
246
|
+
PasteboardItemID id = 0;
|
247
|
+
CFIndex data_length = 0;
|
248
|
+
CFDataRef flavor_data = NULL;
|
249
|
+
CFStringRef flavor_type = NULL;
|
250
|
+
UInt8 *buffer = NULL;
|
251
|
+
VALUE data = Qnil;
|
252
|
+
VALUE encoding = Qnil;
|
253
|
+
|
254
|
+
pasteboard = pb_get_pasteboard(self);
|
255
|
+
|
256
|
+
id = (PasteboardItemID)NUM2ULONG(identifier);
|
257
|
+
|
258
|
+
flavor_type = CFStringCreateWithCString(NULL,
|
259
|
+
value_to_usascii_cstr(flavor),
|
260
|
+
kCFStringEncodingASCII);
|
261
|
+
|
262
|
+
if (flavor_type == NULL)
|
263
|
+
rb_raise(ePBError, "unable to allocate memory for flavor type");
|
264
|
+
|
265
|
+
err = PasteboardCopyItemFlavorData(pasteboard, id, flavor_type, &flavor_data);
|
266
|
+
|
267
|
+
pb_error(err);
|
268
|
+
|
269
|
+
data_length = CFDataGetLength(flavor_data);
|
270
|
+
|
271
|
+
buffer = (UInt8 *)malloc(data_length);
|
272
|
+
|
273
|
+
if (buffer == NULL) {
|
274
|
+
CFRelease(flavor_data);
|
275
|
+
rb_raise(ePBError, "unable to allocate memory for data");
|
276
|
+
}
|
277
|
+
|
278
|
+
CFDataGetBytes(flavor_data, CFRangeMake(0, data_length), buffer);
|
279
|
+
|
280
|
+
CFRelease(flavor_data);
|
281
|
+
|
282
|
+
data = rb_str_new((char *)buffer, data_length);
|
283
|
+
|
284
|
+
free(buffer);
|
285
|
+
|
286
|
+
#if HAVE_RB_STR_ENCODE
|
287
|
+
encoding = rb_hash_aref(cPBTypeEncodings, flavor);
|
288
|
+
|
289
|
+
if (rb_str_equal(flavor, utf16_external_flavor) ||
|
290
|
+
rb_str_equal(flavor, utf16_internal_flavor)) {
|
291
|
+
handle_bom(data, encoding);
|
292
|
+
} else {
|
293
|
+
rb_enc_associate(data, rb_to_encoding(encoding));
|
294
|
+
}
|
295
|
+
#endif
|
296
|
+
|
297
|
+
return data;
|
298
|
+
}
|
299
|
+
|
300
|
+
/*
|
301
|
+
* call-seq:
|
302
|
+
* pasteboard.get_item_count
|
303
|
+
*
|
304
|
+
* The number of items on the pasteboard
|
305
|
+
*/
|
306
|
+
static VALUE
|
307
|
+
pb_get_item_count(VALUE self) {
|
308
|
+
OSStatus err = noErr;
|
309
|
+
PasteboardRef pasteboard;
|
310
|
+
ItemCount item_count = 0;
|
311
|
+
|
312
|
+
pasteboard = pb_get_pasteboard(self);
|
313
|
+
|
314
|
+
err = PasteboardGetItemCount(pasteboard, &item_count);
|
315
|
+
|
316
|
+
pb_error(err);
|
317
|
+
|
318
|
+
return ULONG2NUM(item_count);
|
319
|
+
}
|
320
|
+
|
321
|
+
/*
|
322
|
+
* call-seq:
|
323
|
+
* pasteboard.get_item_identifier index
|
324
|
+
*
|
325
|
+
* The identifier of the pasteboard item at +index+ which is 1-based.
|
326
|
+
*/
|
327
|
+
static VALUE
|
328
|
+
pb_get_item_identifier(VALUE self, VALUE index) {
|
329
|
+
OSStatus err = noErr;
|
330
|
+
PasteboardRef pasteboard;
|
331
|
+
CFIndex item_index = 0;
|
332
|
+
PasteboardItemID item_id = 0;
|
333
|
+
|
334
|
+
item_index = NUM2ULONG(index);
|
335
|
+
|
336
|
+
pasteboard = pb_get_pasteboard(self);
|
337
|
+
|
338
|
+
err = PasteboardGetItemIdentifier(pasteboard, item_index, &item_id);
|
339
|
+
|
340
|
+
pb_error(err);
|
341
|
+
|
342
|
+
return ULONG2NUM((unsigned long)item_id);
|
343
|
+
}
|
344
|
+
|
345
|
+
/*
|
346
|
+
* call-seq:
|
347
|
+
* pasteboard.name
|
348
|
+
*
|
349
|
+
* The name of this pasteboard.
|
350
|
+
*/
|
351
|
+
static VALUE
|
352
|
+
pb_name(VALUE self) {
|
353
|
+
OSStatus err = noErr;
|
354
|
+
PasteboardRef pasteboard;
|
355
|
+
CFStringRef pasteboard_name = NULL;
|
356
|
+
VALUE name = Qnil;
|
357
|
+
|
358
|
+
pasteboard = pb_get_pasteboard(self);
|
359
|
+
|
360
|
+
err = PasteboardCopyName(pasteboard, &pasteboard_name);
|
361
|
+
|
362
|
+
pb_error(err);
|
363
|
+
|
364
|
+
name = string_ref_to_value(pasteboard_name);
|
365
|
+
|
366
|
+
if (pasteboard_name)
|
367
|
+
CFRelease(pasteboard_name);
|
368
|
+
|
369
|
+
return name;
|
370
|
+
}
|
371
|
+
|
372
|
+
/*
|
373
|
+
* call-seq:
|
374
|
+
* pasteboard.sync
|
375
|
+
*
|
376
|
+
* Synchronizes the local pasteboard to reflect the contents of the global
|
377
|
+
* pasteboard.
|
378
|
+
*/
|
379
|
+
static VALUE
|
380
|
+
pb_sync(VALUE self) {
|
381
|
+
PasteboardSyncFlags flags;
|
382
|
+
PasteboardRef pasteboard;
|
383
|
+
|
384
|
+
pasteboard = pb_get_pasteboard(self);
|
385
|
+
|
386
|
+
flags = PasteboardSynchronize(pasteboard);
|
387
|
+
|
388
|
+
return ULONG2NUM(flags);
|
389
|
+
}
|
390
|
+
|
391
|
+
/*
|
392
|
+
* call-seq:
|
393
|
+
* pasteboard.put_item_flavor id, flavor, data
|
394
|
+
*
|
395
|
+
* Puts an item into the pasteboard. +id+ is used to identify an item,
|
396
|
+
* +flavor+ is the item's type and +data+ is the pasteboard data for the item.
|
397
|
+
*/
|
398
|
+
static VALUE
|
399
|
+
pb_put_item_flavor(VALUE self, VALUE id, VALUE flavor, VALUE data) {
|
400
|
+
OSStatus err = noErr;
|
401
|
+
PasteboardRef pasteboard;
|
402
|
+
CFDataRef pasteboard_data = NULL;
|
403
|
+
CFStringRef item_flavor = NULL;
|
404
|
+
|
405
|
+
pasteboard = pb_get_pasteboard(self);
|
406
|
+
|
407
|
+
item_flavor = CFStringCreateWithCString(NULL,
|
408
|
+
value_to_usascii_cstr(flavor),
|
409
|
+
kCFStringEncodingASCII);
|
410
|
+
|
411
|
+
if (item_flavor == NULL)
|
412
|
+
rb_raise(ePBError, "unable to allocate memory for item flavor");
|
413
|
+
|
414
|
+
pasteboard_data = CFDataCreate(kCFAllocatorDefault,
|
415
|
+
(UInt8 *)StringValuePtr(data), RSTRING_LEN(data));
|
416
|
+
|
417
|
+
if (pasteboard_data == NULL) {
|
418
|
+
CFRelease(item_flavor);
|
419
|
+
rb_raise(ePBError, "unable to allocate memory for pasteboard data");
|
420
|
+
}
|
421
|
+
|
422
|
+
err = PasteboardPutItemFlavor(pasteboard,
|
423
|
+
(PasteboardItemID)NUM2ULONG(id),
|
424
|
+
item_flavor,
|
425
|
+
pasteboard_data,
|
426
|
+
kPasteboardFlavorNoFlags);
|
427
|
+
|
428
|
+
CFRelease(item_flavor);
|
429
|
+
CFRelease(pasteboard_data);
|
430
|
+
|
431
|
+
pb_error(err);
|
432
|
+
|
433
|
+
return self;
|
434
|
+
}
|
435
|
+
|
436
|
+
void
|
437
|
+
Init_pasteboard(void) {
|
438
|
+
cPB = rb_define_class("Pasteboard", rb_cObject);
|
439
|
+
|
440
|
+
cPBType = rb_const_get_at(cPB, rb_intern("Type"));
|
441
|
+
ePBError = rb_const_get_at(cPB, rb_intern("Error"));
|
442
|
+
ePBMissing = rb_const_get_at(cPB, rb_intern("Missing"));
|
443
|
+
|
444
|
+
#if HAVE_RB_STR_ENCODE
|
445
|
+
cPBTypeEncodings = rb_const_get_at(cPBType, rb_intern("Encodings"));
|
446
|
+
|
447
|
+
utf8_encoding = rb_enc_from_encoding(rb_utf8_encoding());
|
448
|
+
binary_encoding = rb_const_get_at(rb_cEncoding, rb_intern("BINARY"));
|
449
|
+
utf16be_encoding = rb_const_get_at(rb_cEncoding, rb_intern("UTF_16BE"));
|
450
|
+
utf16le_encoding = rb_const_get_at(rb_cEncoding, rb_intern("UTF_16LE"));
|
451
|
+
native_encoding = rb_const_get_at(cPB, rb_intern("NATIVE_ENCODING"));
|
452
|
+
usascii_encoding = rb_enc_from_encoding(rb_usascii_encoding());
|
453
|
+
|
454
|
+
utf16_external_flavor = rb_const_get_at(cPBType,
|
455
|
+
rb_intern("PLAIN_TEXT_UTF16_EXTERNAL"));
|
456
|
+
|
457
|
+
utf16_internal_flavor = rb_const_get_at(cPBType,
|
458
|
+
rb_intern("PLAIN_TEXT_UTF16"));
|
459
|
+
|
460
|
+
BE_BOM = rb_const_get_at(cPB, rb_intern("BE_BOM"));
|
461
|
+
LE_BOM = rb_const_get_at(cPB, rb_intern("LE_BOM"));
|
462
|
+
#endif
|
463
|
+
|
464
|
+
rb_define_const(cPB, "MODIFIED", ULONG2NUM(kPasteboardModified));
|
465
|
+
rb_define_const(cPB, "CLIENT_IS_OWNER", ULONG2NUM(kPasteboardClientIsOwner));
|
466
|
+
|
467
|
+
rb_define_alloc_func(cPB, pb_alloc);
|
468
|
+
rb_define_method(cPB, "initialize", pb_init, -1);
|
469
|
+
rb_define_method(cPB, "clear", pb_clear, 0);
|
470
|
+
rb_define_method(cPB, "copy_item_flavors", pb_copy_item_flavors, 1);
|
471
|
+
rb_define_method(cPB, "copy_item_flavor_data", pb_copy_item_flavor_data, 2);
|
472
|
+
rb_define_method(cPB, "get_item_count", pb_get_item_count, 0);
|
473
|
+
rb_define_method(cPB, "get_item_identifier", pb_get_item_identifier, 1);
|
474
|
+
rb_define_method(cPB, "name", pb_name, 0);
|
475
|
+
rb_define_method(cPB, "put_item_flavor", pb_put_item_flavor, 3);
|
476
|
+
rb_define_method(cPB, "sync", pb_sync, 0);
|
477
|
+
}
|
478
|
+
|