1 /*
2  * Copyright (c) 2006 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 static GPerlCallback *
gtk2perl_text_buffer_serialize_func_create(SV * func,SV * data)26 gtk2perl_text_buffer_serialize_func_create (SV * func,
27                                             SV * data)
28 {
29         GType param_types[4];
30         param_types[0] = GTK_TYPE_TEXT_BUFFER;
31         param_types[1] = GTK_TYPE_TEXT_BUFFER;
32         param_types[2] = GTK_TYPE_TEXT_ITER;
33         param_types[3] = GTK_TYPE_TEXT_ITER;
34         return gperl_callback_new (func, data, G_N_ELEMENTS (param_types),
35                                    param_types, GPERL_TYPE_SV);
36 }
37 
38 static guint8 *
gtk2perl_text_buffer_serialize_func(GtkTextBuffer * register_buffer,GtkTextBuffer * content_buffer,const GtkTextIter * start,const GtkTextIter * end,gsize * length,gpointer user_data)39 gtk2perl_text_buffer_serialize_func (GtkTextBuffer     *register_buffer,
40                                      GtkTextBuffer     *content_buffer,
41                                      const GtkTextIter *start,
42                                      const GtkTextIter *end,
43                                      gsize             *length,
44                                      gpointer           user_data)
45 {
46         GPerlCallback * callback = (GPerlCallback *) user_data;
47         GValue value = {0, };
48         SV * ret_sv;
49         guint8 * data;
50         g_value_init (&value, GPERL_TYPE_SV);
51         gperl_callback_invoke (callback, &value,
52                                register_buffer, content_buffer, start, end);
53         ret_sv = g_value_get_boxed (&value);
54         if (gperl_sv_is_defined (ret_sv)) {
55                 data = (guint8 *) g_strdup (SvPV (ret_sv, (*length)));
56         } else {
57                 *length = 0;
58                 data = NULL;
59         }
60         g_value_unset (&value);
61 
62         return data;
63 }
64 
65 static GPerlCallback *
gtk2perl_text_buffer_deserialize_func_create(SV * func,SV * data)66 gtk2perl_text_buffer_deserialize_func_create (SV * func,
67                                               SV * data)
68 {
69         GType param_types[5];
70         param_types[0] = GTK_TYPE_TEXT_BUFFER;
71         param_types[1] = GTK_TYPE_TEXT_BUFFER;
72         param_types[2] = GTK_TYPE_TEXT_ITER;
73         param_types[3] = GPERL_TYPE_SV,
74         param_types[4] = G_TYPE_BOOLEAN;
75         return gperl_callback_new (func, data, G_N_ELEMENTS (param_types),
76                                    param_types, G_TYPE_NONE);
77 }
78 
79 static gboolean
gtk2perl_text_buffer_deserialize_func(GtkTextBuffer * register_buffer,GtkTextBuffer * content_buffer,GtkTextIter * iter,const guint8 * data,gsize length,gboolean create_tags,gpointer user_data,GError ** error)80 gtk2perl_text_buffer_deserialize_func (GtkTextBuffer     *register_buffer,
81                                        GtkTextBuffer     *content_buffer,
82                                        GtkTextIter       *iter,
83                                        const guint8      *data,
84                                        gsize              length,
85                                        gboolean           create_tags,
86                                        gpointer           user_data,
87                                        GError           **error)
88 {
89         GPerlCallback *callback = (GPerlCallback*) user_data;
90         gboolean retval = TRUE;
91         dGPERL_CALLBACK_MARSHAL_SP;
92 
93         /* we should trap exceptions and turn those into GErrors.
94          * that will require using call_sv() directly. */
95         GPERL_CALLBACK_MARSHAL_INIT (callback);
96 
97         ENTER;
98         SAVETMPS;
99 
100         PUSHMARK (SP);
101 
102         XPUSHs (sv_2mortal (newSVGtkTextBuffer (register_buffer)));
103         XPUSHs (sv_2mortal (newSVGtkTextBuffer (content_buffer)));
104         XPUSHs (sv_2mortal (newSVGtkTextIter (iter)));
105         XPUSHs (sv_2mortal (newSVpvn ((const char *) data, length)));
106         XPUSHs (sv_2mortal (newSViv (create_tags)));
107         if (callback->data)
108                 XPUSHs (callback->data);
109 
110         PUTBACK;
111 
112         call_sv (callback->func, G_DISCARD | G_EVAL);
113         if (gperl_sv_is_defined (ERRSV) && SvTRUE (ERRSV)) {
114                 if (SvROK (ERRSV) && sv_derived_from (ERRSV, "Glib::Error")) {
115                         gperl_gerror_from_sv (ERRSV, error);
116                 } else {
117                         /* g_error_new_literal() won't let us pass 0 for
118                          * the domain... */
119                         g_set_error (error, 0, 0, "%s", SvPV_nolen (ERRSV));
120                 }
121                 retval = FALSE;
122         }
123 
124         FREETMPS;
125         LEAVE;
126 
127         return retval;
128 }
129 
130 
131 MODULE = Gtk2::TextBufferRichText	PACKAGE = Gtk2::TextBuffer	PREFIX = gtk_text_buffer_
132 
133 
134 GdkAtom gtk_text_buffer_register_serialize_format (GtkTextBuffer *buffer, const gchar *mime_type, SV * function, SV * user_data=NULL);
135     CODE:
136         RETVAL = gtk_text_buffer_register_serialize_format
137                         (buffer, mime_type,
138                          gtk2perl_text_buffer_serialize_func,
139                          gtk2perl_text_buffer_serialize_func_create
140                                                 (function, user_data),
141                          (GDestroyNotify) gperl_callback_destroy);
142     OUTPUT:
143         RETVAL
144 
145 GdkAtom gtk_text_buffer_register_deserialize_format (GtkTextBuffer *buffer, const gchar *mime_type, SV *function, SV *user_data=NULL);
146     CODE:
147         RETVAL = gtk_text_buffer_register_deserialize_format
148                         (buffer, mime_type,
149                          gtk2perl_text_buffer_deserialize_func,
150                          gtk2perl_text_buffer_deserialize_func_create
151                                                 (function, user_data),
152                          (GDestroyNotify) gperl_callback_destroy);
153     OUTPUT:
154         RETVAL
155 
156 GdkAtom gtk_text_buffer_register_serialize_tagset (GtkTextBuffer *buffer, const gchar_ornull *tagset_name);
157 
158 GdkAtom gtk_text_buffer_register_deserialize_tagset (GtkTextBuffer *buffer, const gchar_ornull *tagset_name);
159 
160 void gtk_text_buffer_unregister_serialize_format (GtkTextBuffer *buffer, GdkAtom format);
161 
162 void gtk_text_buffer_unregister_deserialize_format (GtkTextBuffer *buffer, GdkAtom format);
163 
164 void gtk_text_buffer_deserialize_set_can_create_tags (GtkTextBuffer *buffer, GdkAtom format, gboolean can_create_tags);
165 
166 gboolean gtk_text_buffer_deserialize_get_can_create_tags (GtkTextBuffer *buffer, GdkAtom format);
167 
168 void
169 gtk_text_buffer_get_serialize_formats (GtkTextBuffer *buffer);
170     ALIAS:
171         get_deserialize_formats = 1
172     PREINIT:
173         GdkAtom * formats;
174         gint n_formats;
175     PPCODE:
176         if (ix == 1)
177                 formats = gtk_text_buffer_get_deserialize_formats (buffer,
178                                                                    &n_formats);
179         else
180                 formats = gtk_text_buffer_get_serialize_formats (buffer,
181                                                                  &n_formats);
182         if (formats) {
183                 gint i;
184                 EXTEND (SP, n_formats);
185                 for (i = 0 ; i < n_formats ; i++)
186                         PUSHs (sv_2mortal (newSVGdkAtom (formats[i])));
187                 g_free (formats);
188         }
189 
190 SV *
191 gtk_text_buffer_serialize (GtkTextBuffer     * register_buffer, \
192                            GtkTextBuffer     * content_buffer, \
193                            GdkAtom             format, \
194                            const GtkTextIter * start, \
195                            const GtkTextIter * end)
196     PREINIT:
197         guint8 * text;
198         gsize length;
199     CODE:
200         text = gtk_text_buffer_serialize (register_buffer, content_buffer,
201                                           format, start, end, &length);
202         if (!text)
203                 XSRETURN_UNDEF;
204         RETVAL = newSVpvn ((const char *) text, length);
205     OUTPUT:
206         RETVAL
207 
208 =for apidoc __gerror__
209 =cut
210 void
211 gtk_text_buffer_deserialize (GtkTextBuffer     * register_buffer, \
212                              GtkTextBuffer     * content_buffer, \
213                              GdkAtom             format, \
214                              GtkTextIter       * iter, \
215                              SV                * data)
216     PREINIT:
217         GError * error = NULL;
218         guint8 * text;
219         STRLEN length;
220     CODE:
221         text = (guint8 *) SvPV (data, length);
222         if (!gtk_text_buffer_deserialize (register_buffer, content_buffer,
223                                           format, iter, text, length, &error))
224                 gperl_croak_gerror (NULL, error);
225 
226