1 /*
2  * Copyright (c) 2003 by the gtk2-perl team (see the file AUTHORS)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301  USA.
18  *
19  * $Id$
20  */
21 
22 #include "gtk2perl.h"
23 #include <gperl_marshal.h>
24 
25 /*
26 GtkEditable's insert-text signal uses an integer pointer as a write-through
27 parameter; unlike GtkWidget's size-request signal, we can't just pass an
28 editable object, because an integer is an integral type.
29 
30    void user_function  (GtkEditable *editable,
31                         gchar *new_text,
32                         gint new_text_length,
33                         gint *position,  <<=== that's the problem
34                         gpointer user_data);
35 */
36 static void
gtk2perl_editable_insert_text_marshal(GClosure * closure,GValue * return_value,guint n_param_values,const GValue * param_values,gpointer invocation_hint,gpointer marshal_data)37 gtk2perl_editable_insert_text_marshal (GClosure * closure,
38                                        GValue * return_value,
39                                        guint n_param_values,
40                                        const GValue * param_values,
41                                        gpointer invocation_hint,
42                                        gpointer marshal_data)
43 {
44 	STRLEN len;
45 	gint * position_p;
46 	SV * string, * position;
47 	dGPERL_CLOSURE_MARSHAL_ARGS;
48 
49 	GPERL_CLOSURE_MARSHAL_INIT (closure, marshal_data);
50 
51 	PERL_UNUSED_VAR (return_value);
52 	PERL_UNUSED_VAR (n_param_values);
53 	PERL_UNUSED_VAR (invocation_hint);
54 
55 	ENTER;
56 	SAVETMPS;
57 
58 	PUSHMARK (SP);
59 
60 	GPERL_CLOSURE_MARSHAL_PUSH_INSTANCE (param_values);
61 
62 	/* string and position are cleaned up manually further down, so they
63 	 * don't need sv_2mortal. */
64 
65 	/* new_text */
66 	string = newSVGChar (g_value_get_string (param_values+1));
67 	XPUSHs (string);
68 
69 	/* text length is redundant, but documented.  it doesn't hurt
70 	 * anything to include it, but would be a doc hassle to omit it. */
71 	XPUSHs (sv_2mortal (newSViv (g_value_get_int (param_values+2))));
72 
73 	/* insert position */
74 	position_p = g_value_get_pointer (param_values+3);
75 	position = newSViv (*position_p);
76 	XPUSHs (position);
77 
78 	GPERL_CLOSURE_MARSHAL_PUSH_DATA;
79 
80 	PUTBACK;
81 
82 	GPERL_CLOSURE_MARSHAL_CALL (G_ARRAY);
83 
84 	/* refresh the param_values with whatever changes the callback may
85 	 * have made.  values returned on the stack take precedence over
86 	 * modifications to @_. */
87 	if (count == 2) {
88 		SV * sv;
89 		/* get the values off the end of the stack.  why do my
90 		 * attempts to use ST() result in segfaults? */
91 		*position_p = POPi;
92 		sv = POPs;
93 		sv_utf8_upgrade (sv);
94 		g_value_set_string ((GValue*)param_values+1, SvPV (sv, len));
95 		g_value_set_int ((GValue*)param_values+2, len);
96 		PUTBACK;
97 
98 	} else if (count == 0) {
99 		/* returned no values, then refresh string and position
100 		 * params from the callback's args, which may have been
101 		 * modified. */
102 		sv_utf8_upgrade (string);
103 		g_value_set_string ((GValue*)param_values+1,
104 		                    SvPV (string, len));
105 		g_value_set_int ((GValue*)param_values+2, len);
106 		*position_p = SvIV (position);
107 		if (*position_p < 0)
108 			*position_p = 0;
109 
110 	} else {
111 		/* NOTE: croaking here can cause bad things to happen to the
112 		 * app, because croaking in signal handlers is bad juju. */
113 		croak ("an insert-text signal handler must either return"
114 		       " two items (text and position)\nor return no items"
115 		       " and possibly modify its @_ parameters.\n"
116 		       "  callback returned %d items", count);
117 	}
118 
119 	/*
120 	 * clean up
121 	 */
122 	SvREFCNT_dec (string);
123 	SvREFCNT_dec (position);
124 
125 	PUTBACK;
126 	FREETMPS;
127 	LEAVE;
128 }
129 
130 
131 MODULE = Gtk2::Editable	PACKAGE = Gtk2::Editable	PREFIX = gtk_editable_
132 
133 =for position post_signals
134 
135 The C<insert-text> signal handler can optionally alter the text to be
136 inserted.  It may
137 
138 =over 4
139 
140 =item
141 
142 Return no values for no change.  Be sure to end with an empty
143 C<return>.
144 
145     sub my_insert_text_handler {
146       my ($widget, $text, $len, $pos, $userdata) = @_;
147       print "inserting '$text' at char position '$pos'\n";
148       return;  # no values
149     }
150 
151 =item
152 
153 Return two values C<($text, $pos)> which are the new text and
154 character position.
155 
156     sub my_insert_text_handler {
157       my ($widget, $text, $len, $pos, $userdata) = @_;
158       return (uc($text), $pos);  # force to upper case
159     }
160 
161 =item
162 
163 Return no values and modify the text in C<$_[1]> and/or position in
164 C<$_[3]>.  For example,
165 
166     sub my_insert_text_handler {
167       $_[1] = uc($_[1]);   # force to upper case
168       $_[3] = 0;           # force position to the start
169       return;  # no values
170     }
171 
172 =back
173 
174 Note that currently in a Perl subclass of a C<Gtk2::Editable> widget,
175 a class closure (ie. class default signal handler) for C<insert-text>
176 does not work this way.  It instead sees the C level C<($text, $len,
177 $pos_pointer)>, where C<$pos_pointer> is a machine address and cannot
178 be used easily.  Hopefully this will change in the future.
179 A C<signal_chain_from_overridden> with the args as passed works, but
180 for anything else the suggestion is to use a C<signal_connect>
181 instead.
182 
183 =cut
184 
185 BOOT:
186 	gperl_signal_set_marshaller_for (GTK_TYPE_EDITABLE, "insert_text",
187 	                                 gtk2perl_editable_insert_text_marshal);
188 
189 void
190 gtk_editable_select_region (editable, start, end)
191 	GtkEditable *editable
192 	gint start
193 	gint end
194 
195 
196  ## returns an empty list if there is no selection
197 =for apidoc
198 =for signature (start, end) = $editable->get_selection_bounds
199 Returns integers, start and end.
200 =cut
201 void
202 gtk_editable_get_selection_bounds (editable)
203 	GtkEditable *editable
204     PREINIT:
205 	gint start;
206 	gint end;
207     PPCODE:
208 	if (!gtk_editable_get_selection_bounds (editable, &start, &end))
209 		XSRETURN_EMPTY;
210 	EXTEND (SP, 2);
211 	PUSHs (sv_2mortal (newSViv (start)));
212 	PUSHs (sv_2mortal (newSViv (end)));
213 
214 =for apidoc
215 =for signature new_position = $editable->insert_text (new_text, position)
216 =cut
217  ## returns position of next char after inserted text
218 gint
219 gtk_editable_insert_text (editable, new_text, ...)
220 	GtkEditable *editable
221 	gchar *new_text
222     PREINIT:
223 	gint new_text_length;
224 	gint position;
225     CODE:
226 	if (items == 3) {
227 		new_text_length = strlen (new_text);
228 		position = SvIV (ST (2));
229 	} else if (items == 4) {
230 		new_text_length = SvIV (ST (2));
231 		position = SvIV (ST (3));
232 	} else {
233 		croak ("Usage: Gtk2::Editable::insert_text(editable, new_text, position)");
234 	}
235 
236 	gtk_editable_insert_text (editable, new_text,
237 				  new_text_length, &position);
238 	RETVAL = position;
239     OUTPUT:
240 	RETVAL
241 
242 void
243 gtk_editable_delete_text (editable, start_pos, end_pos)
244 	GtkEditable *editable
245 	gint start_pos
246 	gint end_pos
247 
248 gchar_own *
249 gtk_editable_get_chars (editable, start_pos, end_pos)
250 	GtkEditable *editable
251 	gint start_pos
252 	gint end_pos
253 
254 void
255 gtk_editable_cut_clipboard (editable)
256 	GtkEditable *editable
257 
258 void
259 gtk_editable_copy_clipboard (editable)
260 	GtkEditable *editable
261 
262 void
263 gtk_editable_paste_clipboard (editable)
264 	GtkEditable *editable
265 
266 void
267 gtk_editable_delete_selection (editable)
268 	GtkEditable *editable
269 
270 void
271 gtk_editable_set_position (editable, position)
272 	GtkEditable *editable
273 	gint position
274 
275 gint
276 gtk_editable_get_position (editable)
277 	GtkEditable *editable
278 
279 void
280 gtk_editable_set_editable (editable, is_editable)
281 	GtkEditable *editable
282 	gboolean is_editable
283 
284 gboolean
285 gtk_editable_get_editable (editable)
286 	GtkEditable *editable
287 
288