Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / libjava / classpath / native / jni / gtk-peer / gnu_java_awt_peer_gtk_GtkClipboard.c
blob779be57235d44af454dc2dabb45c8cd201434447
1 /* gtkclipboard.c
2 Copyright (C) 1998, 1999, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 #include "jcl.h"
40 #include "gtkpeer.h"
41 #include "gnu_java_awt_peer_gtk_GtkClipboard.h"
43 #define OBJECT_TARGET 1
44 #define TEXT_TARGET 2
45 #define IMAGE_TARGET 3
46 #define URI_TARGET 4
48 /* The clipboard and standard (string targets) shared with GtkSelection. */
49 GtkClipboard *cp_gtk_clipboard;
51 jstring cp_gtk_stringTarget;
52 jstring cp_gtk_imageTarget;
53 jstring cp_gtk_filesTarget;
55 /* Simple id to keep track of the selection we are currently managing. */
56 #if SIZEOF_VOID_P == 8
57 static long current_selection = 0;
58 #else
59 static int current_selection = 0;
60 #endif
62 /* Whether we "own" the clipboard. And may clear it. */
63 static int owner = 0;
65 static jclass gtk_clipboard_class;
66 static jmethodID setSystemContentsID;
68 static jobject gtk_clipboard_instance = NULL;
69 static jmethodID provideContentID;
70 static jmethodID provideTextID;
71 static jmethodID provideImageID;
72 static jmethodID provideURIsID;
74 /* Called when clipboard owner changes. Used to update available targets. */
75 #if GTK_MINOR_VERSION > 4
76 static void
77 clipboard_owner_change_cb (GtkClipboard *clipboard __attribute__((unused)),
78 GdkEvent *event __attribute__((unused)),
79 gpointer user_data __attribute__((unused)))
81 /* These are only interesting when we are not the owner. Otherwise
82 we will have the set and clear functions doing the updating. */
83 JNIEnv *env = cp_gtk_gdk_env ();
84 if (!owner)
85 (*env)->CallStaticVoidMethod (env, gtk_clipboard_class,
86 setSystemContentsID);
88 #endif
90 JNIEXPORT jboolean JNICALL
91 Java_gnu_java_awt_peer_gtk_GtkClipboard_initNativeState (JNIEnv *env,
92 jclass gtkclipboard,
93 jstring string,
94 jstring image,
95 jstring files)
97 GdkDisplay* display;
98 jboolean can_cache;
100 gtk_clipboard_class = gtkclipboard;
101 setSystemContentsID = (*env)->GetStaticMethodID (env, gtk_clipboard_class,
102 "setSystemContents",
103 "()V");
104 if (setSystemContentsID == NULL)
105 return JNI_FALSE;
107 cp_gtk_stringTarget = (*env)->NewGlobalRef(env, string);
108 cp_gtk_imageTarget = (*env)->NewGlobalRef(env, image);
109 cp_gtk_filesTarget = (*env)->NewGlobalRef(env, files);
111 gdk_threads_enter ();
112 cp_gtk_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
114 display = gtk_clipboard_get_display (cp_gtk_clipboard);
115 /* Check for support for clipboard owner changes. */
116 #if GTK_MINOR_VERSION > 4
117 if (gdk_display_supports_selection_notification (display))
119 g_signal_connect (cp_gtk_clipboard, "owner-change",
120 G_CALLBACK (clipboard_owner_change_cb), NULL);
121 gdk_display_request_selection_notification (display,
122 GDK_SELECTION_CLIPBOARD);
123 can_cache = JNI_TRUE;
125 else
126 #endif
127 can_cache = JNI_FALSE;
128 gdk_threads_leave ();
130 return can_cache;
133 static void
134 clipboard_get_func (GtkClipboard *clipboard __attribute__((unused)),
135 GtkSelectionData *selection,
136 guint info,
137 gpointer user_data __attribute__((unused)))
139 JNIEnv *env = cp_gtk_gdk_env ();
141 if (info == OBJECT_TARGET)
143 const gchar *target_name;
144 jstring target_string;
145 jbyteArray bytes;
146 jint len;
147 jbyte *barray;
149 target_name = gdk_atom_name (selection->target);
150 if (target_name == NULL)
151 return;
152 target_string = (*env)->NewStringUTF (env, target_name);
153 if (target_string == NULL)
154 return;
155 bytes = (*env)->CallObjectMethod(env,
156 gtk_clipboard_instance,
157 provideContentID,
158 target_string);
159 if (bytes == NULL)
160 return;
161 len = (*env)->GetArrayLength(env, bytes);
162 if (len <= 0)
163 return;
164 barray = (*env)->GetByteArrayElements(env, bytes, NULL);
165 if (barray == NULL)
166 return;
167 gtk_selection_data_set (selection, selection->target, 8,
168 (guchar *) barray, len);
170 (*env)->ReleaseByteArrayElements(env, bytes, barray, 0);
173 else if (info == TEXT_TARGET)
175 jstring string;
176 const gchar *text;
177 int len;
178 string = (*env)->CallObjectMethod(env,
179 gtk_clipboard_instance,
180 provideTextID);
181 if (string == NULL)
182 return;
183 len = (*env)->GetStringUTFLength (env, string);
184 if (len == -1)
185 return;
186 text = (*env)->GetStringUTFChars (env, string, NULL);
187 if (text == NULL)
188 return;
190 gtk_selection_data_set_text (selection, text, len);
191 (*env)->ReleaseStringUTFChars (env, string, text);
193 /* Images and URIs/Files support only available with gtk+2.6 or higher. */
194 #if GTK_MINOR_VERSION > 4
195 else if (info == IMAGE_TARGET)
197 jobject gtkimage;
198 GdkPixbuf *pixbuf = NULL;
200 gtkimage = (*env)->CallObjectMethod(env,
201 gtk_clipboard_instance,
202 provideImageID);
203 if (gtkimage == NULL)
204 return;
206 pixbuf = cp_gtk_image_get_pixbuf (env, gtkimage);
207 if (pixbuf != NULL)
209 gtk_selection_data_set_pixbuf (selection, pixbuf);
211 /* if the GtkImage is offscreen, this is a temporary pixbuf
212 which should be thrown out. */
213 if(cp_gtk_image_is_offscreen (env, gtkimage) == JNI_TRUE)
214 gdk_pixbuf_unref (pixbuf);
217 else if (info == URI_TARGET)
219 jobjectArray uris;
220 jint count;
221 int i;
222 gchar **list;
224 uris = (*env)->CallObjectMethod(env,
225 gtk_clipboard_instance,
226 provideURIsID);
227 if (uris == NULL)
228 return;
229 count = (*env)->GetArrayLength (env, uris);
230 if (count <= 0)
231 return;
233 list = (gchar **) JCL_malloc (env, (count + 1) * sizeof (gchar *));
234 for (i = 0; i < count; i++)
236 const char *text;
237 jstring uri;
239 /* Mark NULL in so case of some error we can find the end. */
240 list[i] = NULL;
241 uri = (*env)->GetObjectArrayElement (env, uris, i);
242 if (uri == NULL)
243 break;
244 text = (*env)->GetStringUTFChars (env, uri, NULL);
245 if (text == NULL)
246 break;
247 list[i] = strdup (text);
248 (*env)->ReleaseStringUTFChars (env, uri, text);
251 if (i == count)
253 list[count] = NULL;
254 gtk_selection_data_set_uris (selection, list);
257 for (i = 0; list[i] != NULL; i++)
258 free (list[i]);
259 JCL_free (env, list);
261 #endif
264 static void
265 clipboard_clear_func (GtkClipboard *clipboard __attribute__((unused)),
266 gpointer user_data)
268 #if SIZEOF_VOID_P == 8
269 if (owner && (long) user_data == current_selection)
270 #else
271 if (owner && (int) user_data == current_selection)
272 #endif
274 JNIEnv *env = cp_gtk_gdk_env();
275 owner = 0;
276 (*env)->CallStaticVoidMethod (env, gtk_clipboard_class,
277 setSystemContentsID);
281 JNIEXPORT void JNICALL
282 Java_gnu_java_awt_peer_gtk_GtkClipboard_advertiseContent
283 (JNIEnv *env,
284 jobject instance,
285 jobjectArray mime_array,
286 #if GTK_MINOR_VERSION > 4
287 jboolean add_text, jboolean add_images, jboolean add_uris)
288 #else
289 jboolean add_text __attribute__((unused)),
290 jboolean add_images __attribute__((unused)),
291 jboolean add_uris __attribute__((unused)))
292 #endif
294 GtkTargetList *target_list;
295 GList *list;
296 GtkTargetEntry *targets;
297 gint n, i;
299 gdk_threads_enter ();
300 target_list = gtk_target_list_new (NULL, 0);
302 if (mime_array != NULL)
304 n = (*env)->GetArrayLength (env, mime_array);
305 for (i = 0; i < n; i++)
307 const char *text;
308 jstring target;
309 GdkAtom atom;
311 target = (*env)->GetObjectArrayElement (env, mime_array, i);
312 if (target == NULL)
313 break;
314 text = (*env)->GetStringUTFChars (env, target, NULL);
315 if (text == NULL)
316 break;
318 atom = gdk_atom_intern (text, FALSE);
319 gtk_target_list_add (target_list, atom, 0, OBJECT_TARGET);
321 (*env)->ReleaseStringUTFChars (env, target, text);
325 /* Add extra targets that gtk+ can provide/translate for us. */
326 #if GTK_MINOR_VERSION > 4
327 if (add_text)
328 gtk_target_list_add_text_targets (target_list, TEXT_TARGET);
329 if (add_images)
330 gtk_target_list_add_image_targets (target_list, IMAGE_TARGET, TRUE);
331 if (add_uris)
332 gtk_target_list_add_uri_targets (target_list, URI_TARGET);
333 #else
334 if (add_text)
335 gtk_target_list_add (target_list,
336 gdk_atom_intern ("STRING", FALSE),
337 0, TEXT_TARGET);
338 #endif
341 /* Turn list into a target table. */
342 n = g_list_length (target_list->list);
343 if (n > 0)
345 targets = g_new (GtkTargetEntry, n);
346 for (list = target_list->list, i = 0;
347 list != NULL;
348 list = list->next, i++)
350 GtkTargetPair *pair = (GtkTargetPair *) list->data;
351 targets[i].target = gdk_atom_name (pair->target);
352 targets[i].flags = pair->flags;
353 targets[i].info = pair->info;
356 /* Set the targets plus callback functions and ask for the clipboard
357 to be stored when the application exists if supported. */
358 current_selection++;
359 if (gtk_clipboard_set_with_data (cp_gtk_clipboard, targets, n,
360 clipboard_get_func,
361 clipboard_clear_func,
362 (gpointer) current_selection))
364 owner = 1;
365 if (gtk_clipboard_instance == NULL)
367 JNIEnv *env = cp_gtk_gdk_env ();
368 gtk_clipboard_instance = (*env)->NewGlobalRef(env, instance);
370 provideContentID
371 = (*env)->GetMethodID (env, gtk_clipboard_class,
372 "provideContent",
373 "(Ljava/lang/String;)[B");
374 if (provideContentID == NULL)
375 return;
377 provideTextID
378 = (*env)->GetMethodID (env, gtk_clipboard_class,
379 "provideText", "()Ljava/lang/String;");
380 if (provideTextID == NULL)
381 return;
383 provideImageID
384 = (*env)->GetMethodID (env, gtk_clipboard_class,
385 "provideImage",
386 "()Lgnu/java/awt/peer/gtk/GtkImage;");
387 if (provideImageID == NULL)
388 return;
390 provideURIsID
391 = (*env)->GetMethodID (env, gtk_clipboard_class,
392 "provideURIs",
393 "()[Ljava/lang/String;");
394 if (provideURIsID == NULL)
395 return;
397 #if GTK_MINOR_VERSION > 4
398 gtk_clipboard_set_can_store (cp_gtk_clipboard, NULL, 0);
399 #endif
401 else
403 owner = 0;
404 (*env)->CallStaticVoidMethod (env, gtk_clipboard_class,
405 setSystemContentsID);
408 for (i = 0; i < n; i++)
409 g_free (targets[i].target);
410 g_free (targets);
412 else if (owner)
414 gtk_clipboard_clear (cp_gtk_clipboard);
415 owner = 0;
418 gtk_target_list_unref (target_list);
419 gdk_threads_leave ();