1 /* gtktextareapeer.c -- Native implementation of GtkTextAreaPeer
2    Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
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.
10 
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.
15 
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.
20 
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.
25 
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. */
37 
38 
39 #include "gtkpeer.h"
40 #include "gnu_java_awt_peer_gtk_GtkTextAreaPeer.h"
41 
42 #define AWT_TEXTAREA_SCROLLBARS_BOTH 0
43 #define AWT_TEXTAREA_SCROLLBARS_VERTICAL_ONLY 1
44 #define AWT_TEXTAREA_SCROLLBARS_HORIZONTAL_ONLY 2
45 
46 static GtkWidget *textarea_get_widget (GtkWidget *widget);
47 
48 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_create(JNIEnv * env,jobject obj,jint textview_width,jint textview_height,jint scroll)49 Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_create
50   (JNIEnv *env, jobject obj,
51    jint textview_width, jint textview_height,  jint scroll)
52 {
53   GtkWidget *text;
54   GtkWidget *sw;
55   GtkWidget *eventbox;
56 
57   gdk_threads_enter ();
58 
59   /* Create global reference and save it for future use */
60   gtkpeer_set_global_ref (env, obj);
61 
62   text = gtk_text_view_new ();
63   gtk_widget_set_size_request (text, textview_width, textview_height);
64   gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW (text), TRUE);
65 
66   gtk_widget_show (text);
67 
68   eventbox = gtk_event_box_new ();
69   sw = gtk_scrolled_window_new (NULL, NULL);
70   gtk_container_add (GTK_CONTAINER (sw), text);
71   gtk_container_add (GTK_CONTAINER (eventbox), sw);
72   gtk_widget_show (sw);
73 
74   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
75      /* horizontal scrollbar */
76      (scroll == AWT_TEXTAREA_SCROLLBARS_BOTH
77       || scroll == AWT_TEXTAREA_SCROLLBARS_HORIZONTAL_ONLY) ?
78        GTK_POLICY_ALWAYS : GTK_POLICY_NEVER,
79      /* vertical scrollbar */
80      (scroll == AWT_TEXTAREA_SCROLLBARS_BOTH
81       || scroll == AWT_TEXTAREA_SCROLLBARS_VERTICAL_ONLY) ?
82        GTK_POLICY_ALWAYS : GTK_POLICY_NEVER);
83 
84   gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text),
85 			       (scroll == AWT_TEXTAREA_SCROLLBARS_BOTH
86 				|| scroll == AWT_TEXTAREA_SCROLLBARS_HORIZONTAL_ONLY)
87 			       ? GTK_WRAP_NONE : GTK_WRAP_WORD);
88 
89   gtkpeer_set_widget (env, obj, eventbox);
90 
91   gdk_threads_leave ();
92 }
93 
94 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_connectSignals(JNIEnv * env,jobject obj)95 Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_connectSignals
96   (JNIEnv *env, jobject obj)
97 {
98   GtkWidget *text = NULL;
99   GtkTextBuffer *buf;
100   void *ptr;
101   jobject gref;
102 
103   gdk_threads_enter ();
104 
105   ptr = gtkpeer_get_widget (env, obj);
106   gref = gtkpeer_get_global_ref (env, obj);
107 
108   /* Unwrap the text view from the scrolled window */
109   text = textarea_get_widget (GTK_WIDGET (ptr));
110 
111   buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text));
112 
113   /* TextComponent signals */
114   cp_gtk_textcomponent_connect_signals (G_OBJECT (buf), gref);
115 
116   /* Component signals */
117   cp_gtk_component_connect_signals (G_OBJECT (text), gref);
118 
119   gdk_threads_leave ();
120 }
121 
122 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_insert(JNIEnv * env,jobject obj,jstring contents,jint position)123 Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_insert
124   (JNIEnv *env, jobject obj, jstring contents, jint position)
125 {
126   GtkTextBuffer *buf;
127   GtkTextIter iter;
128   GtkWidget *text;
129   void *ptr;
130   const char *str;
131 
132   gdk_threads_enter ();
133 
134   ptr = gtkpeer_get_widget (env, obj);
135   str = (*env)->GetStringUTFChars (env, contents, NULL);
136 
137   text = textarea_get_widget (GTK_WIDGET (ptr));
138 
139   buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text));
140   gtk_text_buffer_get_iter_at_offset (buf, &iter, position);
141   gtk_text_buffer_insert (buf, &iter, str, strlen (str));
142 
143   (*env)->ReleaseStringUTFChars (env, contents, str);
144 
145   gdk_threads_leave ();
146 }
147 
148 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_replaceRange(JNIEnv * env,jobject obj,jstring contents,jint start,jint end)149 Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_replaceRange
150   (JNIEnv *env, jobject obj, jstring contents, jint start, jint end)
151 {
152   GtkWidget *text;
153   GtkTextBuffer *buf;
154   GtkTextIter iter, startIter, endIter;
155   void *ptr;
156   const char *str;
157   int mystart = start;
158   int myend = end;
159 
160   gdk_threads_enter ();
161 
162   ptr = gtkpeer_get_widget (env, obj);
163   str = (*env)->GetStringUTFChars (env, contents, NULL);
164 
165   text = textarea_get_widget (GTK_WIDGET (ptr));
166 
167   buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text));
168 
169   gtk_text_buffer_get_iter_at_offset (buf, &startIter, mystart);
170   gtk_text_buffer_get_iter_at_offset (buf, &endIter, myend);
171   gtk_text_buffer_delete (buf, &startIter, &endIter);
172 
173   gtk_text_buffer_get_iter_at_offset (buf, &iter, mystart);
174   gtk_text_buffer_insert(buf, &iter, str, strlen (str));
175 
176   (*env)->ReleaseStringUTFChars (env, contents, str);
177 
178   gdk_threads_leave ();
179 }
180 
181 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_gtkWidgetModifyFont(JNIEnv * env,jobject obj,jstring name,jint style,jint size)182 Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_gtkWidgetModifyFont
183   (JNIEnv *env, jobject obj, jstring name, jint style, jint size)
184 {
185   const char *font_name;
186   void *ptr;
187   GtkWidget *text;
188   PangoFontDescription *font_desc;
189 
190   gdk_threads_enter();
191 
192   ptr = gtkpeer_get_widget (env, obj);
193 
194   text = textarea_get_widget (GTK_WIDGET (ptr));
195 
196   font_name = (*env)->GetStringUTFChars (env, name, NULL);
197 
198   font_desc = pango_font_description_from_string (font_name);
199   pango_font_description_set_size (font_desc,
200                                    size * cp_gtk_dpi_conversion_factor);
201 
202   if (style & AWT_STYLE_BOLD)
203     pango_font_description_set_weight (font_desc, PANGO_WEIGHT_BOLD);
204 
205   if (style & AWT_STYLE_ITALIC)
206     pango_font_description_set_style (font_desc, PANGO_STYLE_OBLIQUE);
207 
208   gtk_widget_modify_font (GTK_WIDGET (text), font_desc);
209 
210   pango_font_description_free (font_desc);
211 
212   (*env)->ReleaseStringUTFChars (env, name, font_name);
213 
214   gdk_threads_leave();
215 }
216 
217 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_gtkWidgetRequestFocus(JNIEnv * env,jobject obj)218 Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_gtkWidgetRequestFocus
219   (JNIEnv *env, jobject obj)
220 {
221   void *ptr;
222   GtkWidget *text;
223 
224   gdk_threads_enter ();
225 
226   ptr = gtkpeer_get_widget (env, obj);
227 
228   text = textarea_get_widget (GTK_WIDGET (ptr));
229 
230   gtk_widget_grab_focus (text);
231 
232   gdk_threads_leave ();
233 }
234 
235 JNIEXPORT jint JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getHScrollbarHeight(JNIEnv * env,jobject obj)236 Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getHScrollbarHeight
237   (JNIEnv *env, jobject obj)
238 {
239   void *ptr;
240   GtkWidget *bin;
241   GtkScrolledWindow *sw;
242   GtkRequisition requisition;
243   jint height = 0;
244   jint spacing = 0;
245 
246   gdk_threads_enter ();
247 
248   ptr = gtkpeer_get_widget (env, obj);
249 
250   bin = gtk_bin_get_child (GTK_BIN (ptr));
251   sw = GTK_SCROLLED_WINDOW (bin);
252 
253   if (sw)
254     {
255       gtk_widget_size_request (sw->hscrollbar, &requisition);
256       gtk_widget_style_get (GTK_WIDGET (sw), "scrollbar_spacing", &spacing, NULL);
257       height = requisition.height + spacing;
258     }
259 
260   gdk_threads_leave ();
261 
262   return height;
263 }
264 
265 JNIEXPORT jint JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getVScrollbarWidth(JNIEnv * env,jobject obj)266 Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getVScrollbarWidth
267   (JNIEnv *env, jobject obj)
268 {
269   void *ptr;
270   GtkWidget *bin;
271   GtkScrolledWindow *sw;
272   GtkRequisition requisition;
273   jint width = 0;
274   jint spacing = 0;
275 
276   gdk_threads_enter ();
277 
278   ptr = gtkpeer_get_widget (env, obj);
279 
280   bin = gtk_bin_get_child (GTK_BIN (ptr));
281   sw = GTK_SCROLLED_WINDOW (bin);
282 
283   if (sw)
284     {
285       gtk_widget_size_request (sw->vscrollbar, &requisition);
286       gtk_widget_style_get (GTK_WIDGET (sw), "scrollbar_spacing", &spacing, NULL);
287       width = requisition.width + spacing;
288     }
289 
290   gdk_threads_leave ();
291 
292   return width;
293 }
294 
295 JNIEXPORT jint JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getCaretPosition(JNIEnv * env,jobject obj)296 Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getCaretPosition
297   (JNIEnv *env, jobject obj)
298 {
299   void *ptr;
300   int pos = 0;
301   GtkWidget *text = NULL;
302   GtkTextBuffer *buf;
303   GtkTextMark *mark;
304   GtkTextIter iter;
305 
306   gdk_threads_enter ();
307 
308   ptr = gtkpeer_get_widget (env, obj);
309 
310   text = textarea_get_widget (GTK_WIDGET (ptr));
311 
312   buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text));
313   mark = gtk_text_buffer_get_insert (buf);
314   gtk_text_buffer_get_iter_at_mark (buf, &iter, mark);
315   pos = gtk_text_iter_get_offset (&iter);
316 
317   gdk_threads_leave ();
318 
319   return pos;
320 }
321 
322 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_setCaretPosition(JNIEnv * env,jobject obj,jint pos)323 Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_setCaretPosition
324   (JNIEnv *env, jobject obj, jint pos)
325 {
326   void *ptr;
327   GtkWidget *text = NULL;
328   GtkTextBuffer *buf;
329   GtkTextIter iter;
330   GtkTextMark *oldmark;
331   GtkTextIter olditer;
332   int oldpos;
333 
334   gdk_threads_enter ();
335 
336   ptr = gtkpeer_get_widget (env, obj);
337 
338   text = textarea_get_widget (GTK_WIDGET (ptr));
339 
340   buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text));
341 
342   /* Save old position. */
343   oldmark = gtk_text_buffer_get_insert (buf);
344   gtk_text_buffer_get_iter_at_mark (buf, &olditer, oldmark);
345   oldpos = gtk_text_iter_get_offset (&olditer);
346 
347   /* Move to new position. */
348   gtk_text_buffer_get_iter_at_offset (buf, &iter, pos);
349   gtk_text_buffer_place_cursor (buf, &iter);
350 
351   /* Scroll to new position. Alignment is determined
352      comparing the new position to the old position. */
353   if (oldpos > pos)
354     gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (text),
355                                   &iter, 0, TRUE, 0, 0);
356   else if (oldpos < pos)
357     gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (text),
358                                   &iter, 0, TRUE, 1, 1);
359 
360   gdk_threads_leave ();
361 }
362 
363 JNIEXPORT jint JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getSelectionStart(JNIEnv * env,jobject obj)364 Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getSelectionStart
365   (JNIEnv *env, jobject obj)
366 {
367   void *ptr;
368   int pos = 0;
369   GtkWidget *text = NULL;
370   GtkTextBuffer *buf;
371   GtkTextIter start;
372   GtkTextIter end;
373   GtkTextMark *mark;
374   GtkTextIter iter;
375 
376   gdk_threads_enter ();
377 
378   ptr = gtkpeer_get_widget (env, obj);
379 
380   text = textarea_get_widget (GTK_WIDGET (ptr));
381 
382   buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text));
383 
384   if (gtk_text_buffer_get_selection_bounds (buf, &start, &end))
385     {
386       pos = gtk_text_iter_get_offset (&start);
387     }
388   else
389     {
390       mark = gtk_text_buffer_get_insert (buf);
391       gtk_text_buffer_get_iter_at_mark (buf, &iter, mark);
392       pos = gtk_text_iter_get_offset (&iter);
393     }
394 
395   gdk_threads_leave ();
396 
397   return pos;
398 }
399 
400 JNIEXPORT jint JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getSelectionEnd(JNIEnv * env,jobject obj)401 Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getSelectionEnd
402   (JNIEnv *env, jobject obj)
403 {
404   void *ptr;
405   int pos = 0;
406   GtkWidget *text = NULL;
407   GtkTextBuffer *buf;
408   GtkTextIter start;
409   GtkTextIter end;
410   GtkTextMark *mark;
411   GtkTextIter iter;
412 
413   gdk_threads_enter ();
414 
415   ptr = gtkpeer_get_widget (env, obj);
416 
417   text = textarea_get_widget (GTK_WIDGET (ptr));
418 
419   buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text));
420 
421   if (gtk_text_buffer_get_selection_bounds (buf, &start, &end))
422     {
423       pos = gtk_text_iter_get_offset (&end);
424     }
425   else
426     {
427       mark = gtk_text_buffer_get_insert (buf);
428       gtk_text_buffer_get_iter_at_mark (buf, &iter, mark);
429       pos = gtk_text_iter_get_offset (&iter);
430     }
431 
432   gdk_threads_leave ();
433 
434   return pos;
435 }
436 
437 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_select(JNIEnv * env,jobject obj,jint start,jint end)438 Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_select
439   (JNIEnv *env, jobject obj, jint start, jint end)
440 {
441   void *ptr;
442   GtkWidget *text = NULL;
443   GtkTextBuffer *buf;
444   GtkTextIter iter;
445 
446   gdk_threads_enter ();
447 
448   ptr = gtkpeer_get_widget (env, obj);
449 
450   text = textarea_get_widget (GTK_WIDGET (ptr));
451 
452   buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text));
453   gtk_text_buffer_get_iter_at_offset (buf, &iter, start);
454   /* quickly move both 'insert' and 'selection_bound' to the
455      same position */
456   gtk_text_buffer_place_cursor (buf, &iter);
457   gtk_text_buffer_get_iter_at_offset (buf, &iter, end);
458   gtk_text_buffer_move_mark_by_name (buf, "selection_bound", &iter);
459 
460   gdk_threads_leave ();
461 }
462 
463 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_setEditable(JNIEnv * env,jobject obj,jboolean state)464 Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_setEditable
465   (JNIEnv *env, jobject obj, jboolean state)
466 {
467   void *ptr;
468   GtkWidget *text = NULL;
469 
470   gdk_threads_enter ();
471 
472   ptr = gtkpeer_get_widget (env, obj);
473 
474   text = textarea_get_widget (GTK_WIDGET (ptr));
475 
476   gtk_text_view_set_editable (GTK_TEXT_VIEW (text), state);
477 
478   gdk_threads_leave ();
479 }
480 
481 JNIEXPORT jstring JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getText(JNIEnv * env,jobject obj)482 Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_getText
483   (JNIEnv *env, jobject obj)
484 {
485   void *ptr;
486   char *contents = NULL;
487   jstring jcontents;
488   GtkWidget *text = NULL;
489   GtkTextBuffer *buf;
490   GtkTextIter start, end;
491 
492   gdk_threads_enter ();
493 
494   ptr = gtkpeer_get_widget (env, obj);
495 
496   text = textarea_get_widget (GTK_WIDGET (ptr));
497 
498   buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text));
499   gtk_text_buffer_get_start_iter (buf, &start);
500   gtk_text_buffer_get_end_iter (buf, &end);
501   contents = gtk_text_buffer_get_text (buf, &start, &end, FALSE);
502 
503   jcontents = (*env)->NewStringUTF (env, contents);
504   g_free (contents);
505 
506   gdk_threads_leave ();
507 
508   return jcontents;
509 }
510 
511 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_setText(JNIEnv * env,jobject obj,jstring contents)512 Java_gnu_java_awt_peer_gtk_GtkTextAreaPeer_setText
513   (JNIEnv *env, jobject obj, jstring contents)
514 {
515   void *ptr;
516   const char *str;
517   GtkWidget *text = NULL;
518   GtkTextBuffer *buf;
519 
520   gdk_threads_enter ();
521 
522   ptr = gtkpeer_get_widget (env, obj);
523   str = (*env)->GetStringUTFChars (env, contents, NULL);
524 
525   text = textarea_get_widget (GTK_WIDGET (ptr));
526 
527   buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text));
528   gtk_text_buffer_set_text (buf, str, strlen (str));
529 
530   (*env)->ReleaseStringUTFChars (env, contents, str);
531 
532   gdk_threads_leave ();
533 }
534 
535 static GtkWidget *
textarea_get_widget(GtkWidget * widget)536 textarea_get_widget (GtkWidget *widget)
537 {
538    GtkWidget *wid;
539    g_assert (GTK_IS_EVENT_BOX (widget));
540 
541    wid = gtk_bin_get_child (GTK_BIN (widget));
542    g_assert (GTK_IS_SCROLLED_WINDOW (wid));
543 
544    wid = gtk_bin_get_child (GTK_BIN (wid));
545 
546    return wid;
547 }
548