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