This source file includes following definitions.
- android_init_emacs_clipboard
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- DEFUN
- android_xfree_inside
- DEFUN
- init_androidselect
- syms_of_androidselect
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21 #include <assert.h>
22 #include <minmax.h>
23 #include <unistd.h>
24
25 #include "lisp.h"
26 #include "blockinput.h"
27 #include "coding.h"
28 #include "android.h"
29 #include "androidterm.h"
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 struct android_emacs_clipboard
47 {
48 jclass class;
49 jmethodID set_clipboard;
50 jmethodID owns_clipboard;
51 jmethodID clipboard_exists;
52 jmethodID get_clipboard;
53 jmethodID make_clipboard;
54 jmethodID get_clipboard_targets;
55 jmethodID get_clipboard_data;
56 };
57
58
59 static struct android_emacs_clipboard clipboard_class;
60
61
62 static jobject clipboard;
63
64
65
66 static void
67 android_init_emacs_clipboard (void)
68 {
69 jclass old;
70
71 clipboard_class.class
72 = (*android_java_env)->FindClass (android_java_env,
73 "org/gnu/emacs/EmacsClipboard");
74 eassert (clipboard_class.class);
75
76 old = clipboard_class.class;
77 clipboard_class.class
78 = (jclass) (*android_java_env)->NewGlobalRef (android_java_env,
79 old);
80 ANDROID_DELETE_LOCAL_REF (old);
81
82 if (!clipboard_class.class)
83 emacs_abort ();
84
85 #define FIND_METHOD(c_name, name, signature) \
86 clipboard_class.c_name \
87 = (*android_java_env)->GetMethodID (android_java_env, \
88 clipboard_class.class, \
89 name, signature); \
90 assert (clipboard_class.c_name);
91
92 FIND_METHOD (set_clipboard, "setClipboard", "([B)V");
93 FIND_METHOD (owns_clipboard, "ownsClipboard", "()I");
94 FIND_METHOD (clipboard_exists, "clipboardExists", "()Z");
95 FIND_METHOD (get_clipboard, "getClipboard", "()[B");
96 FIND_METHOD (get_clipboard_targets, "getClipboardTargets",
97 "()[[B");
98 FIND_METHOD (get_clipboard_data, "getClipboardData",
99 "([B)[J");
100
101 clipboard_class.make_clipboard
102 = (*android_java_env)->GetStaticMethodID (android_java_env,
103 clipboard_class.class,
104 "makeClipboard",
105 "()Lorg/gnu/emacs/"
106 "EmacsClipboard;");
107 assert (clipboard_class.make_clipboard);
108
109 #undef FIND_METHOD
110 }
111
112
113
114
115 DEFUN ("android-clipboard-owner-p", Fandroid_clipboard_owner_p,
116 Sandroid_clipboard_owner_p, 0, 0, 0,
117 doc:
118
119 )
120 (void)
121 {
122 jint rc;
123
124 if (!android_init_gui)
125 error ("Accessing clipboard without display connection");
126
127 block_input ();
128 rc = (*android_java_env)->CallIntMethod (android_java_env,
129 clipboard,
130 clipboard_class.owns_clipboard);
131 android_exception_check ();
132 unblock_input ();
133
134
135
136
137 if (rc < 0)
138 return Qlambda;
139
140 return rc ? Qt : Qnil;
141 }
142
143 DEFUN ("android-set-clipboard", Fandroid_set_clipboard,
144 Sandroid_set_clipboard, 1, 1, 0,
145 doc: )
146 (Lisp_Object string)
147 {
148 jarray bytes;
149
150 if (!android_init_gui)
151 error ("Accessing clipboard without display connection");
152
153 CHECK_STRING (string);
154 string = ENCODE_UTF_8 (string);
155
156 bytes = (*android_java_env)->NewByteArray (android_java_env,
157 SBYTES (string));
158 android_exception_check ();
159
160 (*android_java_env)->SetByteArrayRegion (android_java_env, bytes,
161 0, SBYTES (string),
162 (jbyte *) SDATA (string));
163 (*android_java_env)->CallVoidMethod (android_java_env,
164 clipboard,
165 clipboard_class.set_clipboard,
166 bytes);
167 android_exception_check_1 (bytes);
168
169 ANDROID_DELETE_LOCAL_REF (bytes);
170 return Qnil;
171 }
172
173 DEFUN ("android-get-clipboard", Fandroid_get_clipboard,
174 Sandroid_get_clipboard, 0, 0, 0,
175 doc:
176
177
178 )
179 (void)
180 {
181 Lisp_Object string;
182 jarray bytes;
183 jmethodID method;
184 size_t length;
185 jbyte *data;
186
187 if (!android_init_gui)
188 error ("No Android display connection!");
189
190 method = clipboard_class.get_clipboard;
191 bytes
192 = (*android_java_env)->CallObjectMethod (android_java_env,
193 clipboard,
194 method);
195 android_exception_check ();
196
197 if (!bytes)
198 return Qnil;
199
200 length = (*android_java_env)->GetArrayLength (android_java_env,
201 bytes);
202 data = (*android_java_env)->GetByteArrayElements (android_java_env,
203 bytes, NULL);
204 android_exception_check_nonnull (data, bytes);
205
206 string = make_unibyte_string ((char *) data, length);
207
208 (*android_java_env)->ReleaseByteArrayElements (android_java_env,
209 bytes, data,
210 JNI_ABORT);
211 ANDROID_DELETE_LOCAL_REF (bytes);
212
213
214 return code_convert_string_norecord (string, Qutf_8, false);
215 }
216
217 DEFUN ("android-clipboard-exists-p", Fandroid_clipboard_exists_p,
218 Sandroid_clipboard_exists_p, 0, 0, 0,
219 doc: )
220 (void)
221 {
222 jboolean rc;
223 jmethodID method;
224
225 if (!android_init_gui)
226 error ("No Android display connection");
227
228 method = clipboard_class.clipboard_exists;
229 rc = (*android_java_env)->CallBooleanMethod (android_java_env,
230 clipboard,
231 method);
232 android_exception_check ();
233
234 return rc ? Qt : Qnil;
235 }
236
237 DEFUN ("android-browse-url", Fandroid_browse_url,
238 Sandroid_browse_url, 1, 2, 0,
239 doc:
240
241
242
243
244
245 )
246 (Lisp_Object url, Lisp_Object send)
247 {
248 Lisp_Object value;
249
250 if (!android_init_gui)
251 error ("No Android display connection!");
252
253 CHECK_STRING (url);
254 value = android_browse_url (url, send);
255
256
257 if (!NILP (value))
258 signal_error ("Error browsing URL", value);
259
260 return Qnil;
261 }
262
263
264
265
266
267
268 DEFUN ("android-get-clipboard-targets", Fandroid_get_clipboard_targets,
269 Sandroid_get_clipboard_targets, 0, 0, 0,
270 doc:
271
272 )
273 (void)
274 {
275 jarray bytes_array;
276 jbyteArray bytes;
277 jmethodID method;
278 size_t length, length1, i;
279 jbyte *data;
280 Lisp_Object targets, tem;
281
282 if (!android_init_gui)
283 error ("No Android display connection!");
284
285 targets = Qnil;
286 block_input ();
287 method = clipboard_class.get_clipboard_targets;
288 bytes_array = (*android_java_env)->CallObjectMethod (android_java_env,
289 clipboard, method);
290 android_exception_check ();
291
292 if (!bytes_array)
293 goto fail;
294
295 length = (*android_java_env)->GetArrayLength (android_java_env,
296 bytes_array);
297 for (i = 0; i < length; ++i)
298 {
299
300 bytes
301 = (*android_java_env)->GetObjectArrayElement (android_java_env,
302 bytes_array, i);
303 android_exception_check_nonnull (bytes, bytes_array);
304
305
306 length1 = (*android_java_env)->GetArrayLength (android_java_env,
307 bytes);
308 data = (*android_java_env)->GetByteArrayElements (android_java_env,
309 bytes, NULL);
310 android_exception_check_nonnull_1 (data, bytes, bytes_array);
311
312
313 tem = make_unibyte_string ((char *) data, length1);
314 tem = code_convert_string_norecord (tem, Qutf_8, false);
315 targets = Fcons (tem, targets);
316
317
318 (*android_java_env)->ReleaseByteArrayElements (android_java_env,
319 bytes, data,
320 JNI_ABORT);
321 ANDROID_DELETE_LOCAL_REF (bytes);
322 }
323 unblock_input ();
324
325 ANDROID_DELETE_LOCAL_REF (bytes_array);
326 return Fnreverse (targets);
327
328 fail:
329 unblock_input ();
330 return Qnil;
331 }
332
333
334
335 static void
336 android_xfree_inside (void *ptr)
337 {
338 xfree (*(char **) ptr);
339 }
340
341 DEFUN ("android-get-clipboard-data", Fandroid_get_clipboard_data,
342 Sandroid_get_clipboard_data, 1, 1, 0,
343 doc:
344
345
346
347
348
349
350
351 )
352 (Lisp_Object type)
353 {
354 jlongArray array;
355 jbyteArray bytes;
356 jmethodID method;
357 int fd;
358 ptrdiff_t rc;
359 jlong offset, length, *longs;
360 specpdl_ref ref;
361 char *buffer, *start;
362
363 if (!android_init_gui)
364 error ("No Android display connection!");
365
366
367 CHECK_STRING (type);
368 type = ENCODE_UTF_8 (type);
369
370
371 block_input ();
372 bytes = (*android_java_env)->NewByteArray (android_java_env,
373 SBYTES (type));
374 (*android_java_env)->SetByteArrayRegion (android_java_env, bytes,
375 0, SBYTES (type),
376 (jbyte *) SDATA (type));
377 android_exception_check ();
378
379 method = clipboard_class.get_clipboard_data;
380 array = (*android_java_env)->CallObjectMethod (android_java_env,
381 clipboard, method,
382 bytes);
383 android_exception_check_1 (bytes);
384 ANDROID_DELETE_LOCAL_REF (bytes);
385
386 if (!array)
387 goto fail;
388
389 longs = (*android_java_env)->GetLongArrayElements (android_java_env,
390 array, NULL);
391 android_exception_check_nonnull (longs, array);
392
393
394
395
396
397 fd = longs[0];
398 offset = longs[1];
399 length = longs[2];
400
401 (*android_java_env)->ReleaseLongArrayElements (android_java_env,
402 array, longs,
403 JNI_ABORT);
404 ANDROID_DELETE_LOCAL_REF (array);
405 unblock_input ();
406
407
408 ref = SPECPDL_INDEX ();
409 record_unwind_protect_int (close_file_unwind, fd);
410
411 if (length != -1)
412 {
413 buffer = xmalloc (MIN (length, PTRDIFF_MAX));
414 record_unwind_protect_ptr (xfree, buffer);
415
416 rc = emacs_read_quit (fd, buffer,
417 MIN (length, PTRDIFF_MAX));
418
419
420 if (rc < 0)
421 return unbind_to (ref, Qnil);
422
423
424 return unbind_to (ref, make_unibyte_string (buffer, rc));
425 }
426
427
428 buffer = xmalloc (BUFSIZ);
429 length = 0;
430 start = buffer;
431
432 record_unwind_protect_ptr (android_xfree_inside, &buffer);
433
434
435
436 if (offset)
437 {
438 if (lseek (fd, offset, SEEK_SET) < 0)
439 return unbind_to (ref, Qnil);
440 }
441
442 while (true)
443 {
444 rc = emacs_read_quit (fd, start, BUFSIZ);
445
446 if (!INT_ADD_OK (rc, length, &length)
447 || PTRDIFF_MAX - length < BUFSIZ)
448 memory_full (PTRDIFF_MAX);
449
450 if (rc < 0)
451 return unbind_to (ref, Qnil);
452
453 if (rc < BUFSIZ)
454 break;
455
456 buffer = xrealloc (buffer, length + BUFSIZ);
457 start = buffer + length;
458 }
459
460 return unbind_to (ref, make_unibyte_string (buffer, rc));
461
462 fail:
463 unblock_input ();
464 return Qnil;
465 }
466
467
468
469 void
470 init_androidselect (void)
471 {
472 jobject tem;
473 jmethodID make_clipboard;
474
475 if (!android_init_gui)
476 return;
477
478 android_init_emacs_clipboard ();
479
480 make_clipboard = clipboard_class.make_clipboard;
481 tem
482 = (*android_java_env)->CallStaticObjectMethod (android_java_env,
483 clipboard_class.class,
484 make_clipboard);
485 if (!tem)
486 emacs_abort ();
487
488 clipboard = (*android_java_env)->NewGlobalRef (android_java_env, tem);
489
490 if (!clipboard)
491 emacs_abort ();
492
493 ANDROID_DELETE_LOCAL_REF (tem);
494 }
495
496 void
497 syms_of_androidselect (void)
498 {
499 defsubr (&Sandroid_clipboard_owner_p);
500 defsubr (&Sandroid_set_clipboard);
501 defsubr (&Sandroid_get_clipboard);
502 defsubr (&Sandroid_clipboard_exists_p);
503 defsubr (&Sandroid_browse_url);
504 defsubr (&Sandroid_get_clipboard_targets);
505 defsubr (&Sandroid_get_clipboard_data);
506 }