Mercurial > pidgin
annotate src/gtkdialogs.c @ 10138:5fb5c447eb4f
[gaim-migrate @ 11208]
Bring back the old smiley selection dialog for gtk<2.4 and play around
with the signals for both of them. We're not explicitly freeing the
smiley menu in gtk2.4 anymore... can someone verify that gtk is
freeing it for us? Or write a patch to free it, if not? This would
probably be a pretty big memleak if gtk isn't taking care of it...
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 25 Oct 2004 02:48:38 +0000 |
parents | a6c3b931214f |
children | 0b43f6fef9b5 |
rev | line source |
---|---|
9709 | 1 /* |
2 * gaim | |
3 * | |
4 * Gaim is the legal property of its developers, whose names are too numerous | |
5 * to list here. Please refer to the COPYRIGHT file distributed with this | |
6 * source distribution. | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 */ | |
9791 | 22 #include "internal.h" |
23 #include "gtkgaim.h" | |
9709 | 24 |
25 #include "debug.h" | |
26 #include "notify.h" | |
27 #include "prpl.h" | |
28 #include "request.h" | |
29 #include "util.h" | |
30 | |
31 #include "gtkdialogs.h" | |
32 #include "gtkimhtml.h" | |
33 #include "gtkimhtmltoolbar.h" | |
34 #include "gtklog.h" | |
35 #include "gtkutils.h" | |
36 #include "stock.h" | |
37 | |
9753 | 38 static GList *dialogwindows = NULL; |
9709 | 39 |
9753 | 40 static GtkWidget *about = NULL; |
9709 | 41 |
42 struct warning { | |
43 GtkWidget *window; | |
44 GtkWidget *anon; | |
45 char *who; | |
46 GaimConnection *gc; | |
47 }; | |
48 | |
9758 | 49 struct developer { |
50 char *name; | |
51 char *role; | |
52 char *email; | |
53 }; | |
54 | |
55 struct translator { | |
56 char *language; | |
57 char *abbr; | |
58 char *name; | |
59 char *email; | |
60 }; | |
61 | |
62 static struct developer developers[] = { | |
63 {"Rob Flynn", N_("maintainer"), "gaim@robflynn.com"}, | |
64 {"Sean Egan", N_("lead developer"), "sean.egan@binghamton.edu"}, | |
65 {"Christian 'ChipX86' Hammond", N_("developer & webmaster"), NULL}, | |
10095
b28f9be379b3
[gaim-migrate @ 11114]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
9991
diff
changeset
|
66 {"Herman Bloggs", N_("win32 port"), "herman@bluedigits.com"}, |
9758 | 67 {"Nathan 'faceprint' Walp", N_("developer"), NULL}, |
68 {"Mark 'KingAnt' Doliner", N_("developer"), NULL}, | |
69 {"Ethan 'Paco-Paco' Blanton", N_("developer"), NULL}, | |
70 {"Tim 'marv' Ringenbach", N_("developer"), NULL}, | |
71 {"Luke 'LSchiere' Schierer", N_("support"), NULL}, | |
10116 | 72 {"Stu 'nosnilmot' Tomlinson", N_("developer"), NULL}, |
9758 | 73 {NULL, NULL, NULL} |
74 }; | |
75 | |
76 static struct developer retired_developers[] = { | |
77 {"Adam Fritzler", N_("former libfaim maintainer"), NULL}, | |
78 {"Eric Warmenhoven", N_("former lead developer"), "warmenhoven@yahoo.com"}, | |
79 {"Jim Duchek", N_("former maintainer"), NULL}, | |
80 {"Jim Seymour", N_("former Jabber developer"), NULL}, | |
81 {"Mark Spencer", N_("original author"), "markster@marko.net"}, | |
82 {"Syd Logan", N_("hacker and designated driver [lazy bum]"), NULL}, | |
83 {NULL, NULL, NULL} | |
84 }; | |
85 | |
86 static struct translator current_translators[] = { | |
87 {N_("Bulgarian"), "bg", "Alexander Shopov", "al_shopov@users.sf.net"}, | |
10131 | 88 {N_("Catalan"), "ca", "Josep Puigdemont", "tradgnome@softcatala.org"}, |
9758 | 89 {N_("Czech"), "cs", "Miloslav Trmac", "mitr@volny.cz"}, |
90 {N_("Danish"), "da", "Morten Brix Pedersen", "morten@wtf.dk"}, | |
10131 | 91 {N_("Australian English"), "en_AU", "Peter Lawler", "trans@six-by-nine.com.au"}, |
9758 | 92 {N_("British English"), "en_GB", "Luke Ross", "lukeross@sys3175.co.uk"}, |
93 {N_("Canadian English"), "en_CA", "Adam Weinberger", "adamw@gnome.org"}, | |
94 {N_("German"), "de", "Björn Voigt", "bjoern@cs.tu-berlin.de"}, | |
95 {N_("Spanish"), "es", "Javier Fernández-Sanguino Peña", "jfs@debian.org"}, | |
96 {N_("Finnish"), "fi", "Arto Alakulju", "arto@alakulju.net"}, | |
97 {N_("French"), "fr", "Éric Boumaour", "zongo_fr@users.sourceforge.net"}, | |
98 {N_("Hebrew"), "he", "Pavel Bibergal", "cyberkm203@hotmail.com"}, | |
99 {N_("Hindi"), "hi", "Ravishankar Shrivastava", "raviratlami@yahoo.com"}, | |
100 {N_("Hungarian"), "hu", "Zoltan Sutto", "suttozoltan@chello.hu"}, | |
101 {N_("Italian"), "it", "Claudio Satriano", "satriano@na.infn.it"}, | |
102 {N_("Japanese"), "ja", "Takashi Aihana", "aihana@gnome.gr.jp"}, | |
103 {N_("Lithuanian"), "lt", "Gediminas Čičinskas", "gediminas@parok.lt"}, | |
104 {N_("Korean"), "ko", "Kyung-uk Son", "vvs740@chol.com"}, | |
105 {N_("Dutch; Flemish"), "nl", "Vincent van Adrighem", "V.vanAdrighem@dirck.mine.nu"}, | |
106 {N_("Macedonian"), "mk", "Tomislav Markovski", "herrera@users.sf.net"}, | |
107 {N_("Norwegian"), "no", "Petter Johan Olsen", "petter.olsen@cc.uit.no"}, | |
108 {N_("Polish"), "pl", "Krzysztof Foltman, Emil Nowak", "krzysztof@foltman.com;emil5@go2.pl"}, | |
109 {N_("Portuguese"), "pt", "Duarte Henriques", "duarte_henriques@myrealbox.com"}, | |
110 {N_("Portuguese-Brazil"), "pt_BR", "Maurício de Lemos Rodrigues Collares Neto", "mauricioc@gmail.com"}, | |
111 {N_("Romanian"), "ro", "Mişu Moldovan", "dumol@go.ro"}, | |
112 {N_("Russian"), "ru", "Dmitry Beloglazov", "dmaa@users.sf.net"}, | |
113 {N_("Serbian"), "sr", "Danilo Šegan, Aleksandar Urosevic", "dsegan@gmx.net;urke@users.sourceforge.net"}, | |
114 {N_("Slovenian"), "sl", "Matjaz Horvat", "matjaz@owca.info"}, | |
115 {N_("Swedish"), "sv", "Tore Lundqvist", "tlt@mima.x.se"}, | |
116 {N_("Vietnamese"), "vi", N_("T.M.Thanh and the Gnome-Vi Team"), "gnomevi-list@lists.sf.net"}, | |
117 {N_("Simplified Chinese"), "zh_CN", "Funda Wang", "fundawang@linux.net.cn"}, | |
118 {N_("Traditional Chinese"), "zh_TW", "Ambrose C. Li, Paladin R. Liu", "acli@ada.dhs.org;paladin@ms1.hinet.net"}, | |
119 {NULL, NULL, NULL, NULL} | |
120 }; | |
121 | |
122 | |
123 static struct translator past_translators[] = { | |
124 {N_("Amharic"), "am", "Daniel Yacob", NULL}, | |
125 {N_("Bulgarian"), "bg", "Hristo Todorov", NULL}, | |
126 {N_("Catalan"), "ca", "JM Pérez Cáncer", NULL}, | |
10131 | 127 {N_("Catalan"), "ca", "Robert Millan", NULL}, |
9758 | 128 {N_("Czech"), "cs", "Honza Král", NULL}, |
129 {N_("German"), "de", "Daniel Seifert, Karsten Weiss", NULL}, | |
130 {N_("Spanish"), "es", "Amaya Rodrigo, Alejandro G Villar, Nicolás Lichtmaier, JM Pérez Cáncer", NULL}, | |
131 {N_("Finnish"), "fi", "Tero Kuusela", NULL}, | |
132 {N_("French"), "fr", "Sébastien François, Stéphane Pontier, Stéphane Wirtel, Loïc Jeannin", NULL}, | |
133 {N_("Italian"), "it", "Salvatore di Maggio", NULL}, | |
134 {N_("Japanese"), "ja", "Ryosuke Kutsuna, Taku Yasui, Junichi Uekawa", NULL}, | |
135 {N_("Korean"), "ko", "Sang-hyun S, A Ho-seok Lee", NULL}, | |
136 {N_("Polish"), "pl", "Przemysław Sułek", NULL}, | |
137 {N_("Russian"), "ru", "Sergey Volozhanin", NULL}, | |
138 {N_("Russian"), "ru", "Alexandre Prokoudine", NULL}, | |
139 {N_("Slovak"), "sk", "Daniel Režný", NULL}, | |
140 {N_("Swedish"), "sv", "Christian Rose", NULL}, | |
141 {N_("Chinese"), "zh_CN, zh_TW", "Hashao, Rocky S. Lee", NULL}, | |
142 {NULL, NULL, NULL, NULL} | |
143 }; | |
144 | |
9730 | 145 void |
146 gaim_gtkdialogs_destroy_all() | |
9709 | 147 { |
9753 | 148 while (dialogwindows) { |
149 gtk_widget_destroy(dialogwindows->data); | |
150 dialogwindows = g_list_remove(dialogwindows, dialogwindows->data); | |
151 } | |
152 } | |
153 | |
154 static void destroy_about() | |
155 { | |
156 if (about != NULL) | |
157 gtk_widget_destroy(about); | |
158 about = NULL; | |
159 } | |
160 | |
161 void gaim_gtkdialogs_about(GtkWidget *w, void *data) | |
162 { | |
163 GtkWidget *hbox; | |
164 GtkWidget *vbox; | |
165 GtkWidget *logo; | |
166 GtkWidget *label; | |
167 GtkWidget *sw; | |
168 GtkWidget *text; | |
169 GtkWidget *bbox; | |
170 GtkWidget *button; | |
171 GtkTextIter iter; | |
9758 | 172 GString *str; |
173 gchar *labeltext; | |
174 int i; | |
9753 | 175 |
176 if (about != NULL) { | |
177 gtk_window_present(GTK_WINDOW(about)); | |
178 return; | |
179 } | |
180 | |
181 GAIM_DIALOG(about); | |
182 gtk_window_set_default_size(GTK_WINDOW(about), 450, -1); | |
183 gtk_window_set_title(GTK_WINDOW(about), _("About Gaim")); | |
184 gtk_window_set_role(GTK_WINDOW(about), "about"); | |
185 gtk_window_set_resizable(GTK_WINDOW(about), TRUE); | |
9778 | 186 gtk_window_set_default_size(GTK_WINDOW(about), 340, 550); /* Golden ratio in da hizzy */ |
9753 | 187 |
188 hbox = gtk_hbox_new(FALSE, 12); | |
189 gtk_container_set_border_width(GTK_CONTAINER(hbox), 12); | |
190 gtk_container_add(GTK_CONTAINER(about), hbox); | |
191 | |
192 vbox = gtk_vbox_new(FALSE, 12); | |
193 gtk_container_add(GTK_CONTAINER(hbox), vbox); | |
194 | |
195 logo = gtk_image_new_from_stock(GAIM_STOCK_LOGO, gtk_icon_size_from_name(GAIM_ICON_SIZE_LOGO)); | |
196 gtk_box_pack_start(GTK_BOX(vbox), logo, FALSE, FALSE, 0); | |
197 | |
198 labeltext = g_strdup_printf(_("<span weight=\"bold\" size=\"larger\">Gaim v%s</span>"), VERSION); | |
199 label = gtk_label_new(NULL); | |
200 gtk_label_set_markup(GTK_LABEL(label), labeltext); | |
201 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); | |
202 gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0); | |
203 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); | |
204 g_free(labeltext); | |
205 | |
206 sw = gtk_scrolled_window_new(NULL, NULL); | |
207 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | |
208 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); | |
209 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN); | |
9758 | 210 gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); |
9753 | 211 |
212 text = gtk_imhtml_new(NULL, NULL); | |
213 gtk_container_add(GTK_CONTAINER(sw), text); | |
214 gaim_setup_imhtml(text); | |
215 | |
9758 | 216 str = g_string_sized_new(4096); |
9753 | 217 |
9758 | 218 g_string_append(str, |
219 _("Gaim is a modular messaging client capable of using " | |
220 "AIM, MSN, Yahoo!, Jabber, ICQ, IRC, SILC, " | |
221 "Novell GroupWise, Napster, Zephyr, and Gadu-Gadu " | |
222 "all at once. It is written using " | |
223 "Gtk+ and is licensed under the GPL.<BR><BR>")); | |
9753 | 224 |
9758 | 225 g_string_append(str, "<FONT SIZE=\"4\">URL:</FONT> <A HREF=\"" |
226 GAIM_WEBSITE "\">" GAIM_WEBSITE "</A><BR/><BR/>"); | |
227 | |
228 g_string_append_printf(str, _("<FONT SIZE=\"4\">IRC:</FONT> " | |
229 "#gaim on irc.freenode.net<BR><BR>")); | |
9753 | 230 |
231 /* Active Developers */ | |
9758 | 232 g_string_append_printf(str, "<FONT SIZE=\"4\">%s:</FONT><BR/>", |
233 _("Active Developers")); | |
234 for (i = 0; developers[i].name != NULL; i++) { | |
235 if (developers[i].email != NULL) { | |
10116 | 236 g_string_append_printf(str, " %s (%s) <<a href=\"mailto:%s\">%s</a>><br/>", |
9758 | 237 developers[i].name, _(developers[i].role), |
238 developers[i].email, developers[i].email); | |
239 } else { | |
240 g_string_append_printf(str, " %s (%s)<br/>", | |
241 developers[i].name, _(developers[i].role)); | |
242 } | |
243 } | |
244 g_string_append(str, "<BR/>"); | |
9709 | 245 |
9753 | 246 /* Crazy Patch Writers */ |
9758 | 247 g_string_append_printf(str, "<FONT SIZE=\"4\">%s:</FONT><BR/>", |
248 _("Crazy Patch Writers")); | |
249 g_string_append(str, | |
250 " Daniel 'datallah' Atallah<BR>" | |
251 " Ka-Hing 'javabsp' Cheung<BR>" | |
9905 | 252 " Felipe 'shx' Contreras<BR>" |
9758 | 253 " Decklin Foster<BR>" |
254 " Gary 'grim' Kramlich<BR>" | |
255 " Robert 'Robot101' McQueen<BR>" | |
256 " Benjamin Miller<BR>" | |
257 " Etan 'deryni' Reisner<BR>" | |
258 " Kevin 'SimGuy' Stange<BR>" | |
259 "<BR>"); | |
9753 | 260 |
261 /* Retired Developers */ | |
9758 | 262 g_string_append_printf(str, "<FONT SIZE=\"4\">%s:</FONT><BR/>", |
263 _("Retired Developers")); | |
264 for (i = 0; retired_developers[i].name != NULL; i++) { | |
265 if (retired_developers[i].email != NULL) { | |
10116 | 266 g_string_append_printf(str, " %s (%s) <<a href=\"mailto:%s\">%s</a>><br/>", |
9758 | 267 retired_developers[i].name, _(retired_developers[i].role), |
268 retired_developers[i].email, retired_developers[i].email); | |
269 } else { | |
270 g_string_append_printf(str, " %s (%s)<br/>", | |
271 retired_developers[i].name, _(retired_developers[i].role)); | |
272 } | |
273 } | |
274 g_string_append(str, "<BR/>"); | |
9753 | 275 |
276 /* Current Translators */ | |
9758 | 277 g_string_append_printf(str, "<FONT SIZE=\"4\">%s:</FONT><BR/>", |
278 _("Current Translators")); | |
279 for (i = 0; current_translators[i].language != NULL; i++) { | |
280 if (current_translators[i].email != NULL) { | |
10116 | 281 g_string_append_printf(str, " <b>%s (%s)</b> - %s <<a href=\"mailto:%s\">%s</a>><br/>", |
9758 | 282 _(current_translators[i].language), |
283 current_translators[i].abbr, | |
284 _(current_translators[i].name), | |
285 current_translators[i].email, | |
286 current_translators[i].email); | |
287 } else { | |
288 g_string_append_printf(str, " <b>%s (%s)</b> - %s<br/>", | |
289 _(current_translators[i].language), | |
290 current_translators[i].abbr, | |
291 _(current_translators[i].name)); | |
292 } | |
293 } | |
294 g_string_append(str, "<BR/>"); | |
9753 | 295 |
296 /* Past Translators */ | |
9758 | 297 g_string_append_printf(str, "<FONT SIZE=\"4\">%s:</FONT><BR/>", |
298 _("Past Translators")); | |
299 for (i = 0; past_translators[i].language != NULL; i++) { | |
300 if (past_translators[i].email != NULL) { | |
10116 | 301 g_string_append_printf(str, " <b>%s (%s)</b> - %s <<a href=\"mailto:%s\">%s</a>><br/>", |
9758 | 302 _(past_translators[i].language), |
303 past_translators[i].abbr, | |
304 _(past_translators[i].name), | |
305 past_translators[i].email, | |
306 past_translators[i].email); | |
307 } else { | |
308 g_string_append_printf(str, " <b>%s (%s)</b> - %s<br/>", | |
309 _(past_translators[i].language), | |
310 past_translators[i].abbr, | |
311 _(past_translators[i].name)); | |
312 } | |
313 } | |
314 g_string_append(str, "<BR/>"); | |
315 | |
316 gtk_imhtml_append_text(GTK_IMHTML(text), str->str, GTK_IMHTML_NO_SCROLL); | |
317 g_string_free(str, TRUE); | |
9753 | 318 |
319 gtk_adjustment_set_value(gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(sw)), 0); | |
320 gtk_text_buffer_get_start_iter(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)), &iter); | |
321 gtk_text_buffer_place_cursor(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)), &iter); | |
322 | |
323 /* Close Button */ | |
324 bbox = gtk_hbutton_box_new(); | |
325 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); | |
326 gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0); | |
327 | |
328 button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); | |
329 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0); | |
330 | |
331 g_signal_connect_swapped(G_OBJECT(button), "clicked", | |
332 G_CALLBACK(destroy_about), G_OBJECT(about)); | |
333 g_signal_connect(G_OBJECT(about), "destroy", | |
334 G_CALLBACK(destroy_about), G_OBJECT(about)); | |
335 | |
336 /* this makes the sizes not work? */ | |
337 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); | |
338 gtk_widget_grab_default(button); | |
339 | |
340 /* Let's give'em something to talk about -- woah woah woah */ | |
341 gtk_widget_show_all(about); | |
342 gtk_window_present(GTK_WINDOW(about)); | |
9709 | 343 } |
344 | |
9730 | 345 static void |
346 gaim_gtkdialogs_im_cb(gpointer data, GaimRequestFields *fields) | |
9709 | 347 { |
9730 | 348 GaimAccount *account; |
349 const char *username; | |
9709 | 350 |
9730 | 351 account = gaim_request_fields_get_account(fields, "account"); |
352 username = gaim_request_fields_get_string(fields, "screenname"); | |
9709 | 353 |
9730 | 354 gaim_gtkdialogs_im_with_user(account, username); |
9709 | 355 } |
356 | |
9730 | 357 void |
358 gaim_gtkdialogs_im(void) | |
9709 | 359 { |
9730 | 360 GaimRequestFields *fields; |
361 GaimRequestFieldGroup *group; | |
362 GaimRequestField *field; | |
9709 | 363 |
9730 | 364 fields = gaim_request_fields_new(); |
9709 | 365 |
9730 | 366 group = gaim_request_field_group_new(NULL); |
367 gaim_request_fields_add_group(fields, group); | |
9709 | 368 |
9730 | 369 field = gaim_request_field_string_new("screenname", _("_Screen name"), |
370 NULL, FALSE); | |
371 gaim_request_field_set_required(field, TRUE); | |
372 gaim_request_field_set_type_hint(field, "screenname"); | |
373 gaim_request_field_group_add_field(group, field); | |
9709 | 374 |
9730 | 375 field = gaim_request_field_account_new("account", _("_Account"), NULL); |
376 gaim_request_field_set_visible(field, | |
377 (gaim_connections_get_all() != NULL && | |
378 gaim_connections_get_all()->next != NULL)); | |
379 gaim_request_field_set_required(field, TRUE); | |
380 gaim_request_field_group_add_field(group, field); | |
381 | |
382 gaim_request_fields(gaim_get_blist(), _("New Instant Message"), | |
383 NULL, | |
384 _("Please enter the screen name of the person you " | |
385 "would like to IM."), | |
386 fields, | |
387 _("OK"), G_CALLBACK(gaim_gtkdialogs_im_cb), | |
388 _("Cancel"), NULL, | |
389 NULL); | |
9709 | 390 } |
391 | |
9730 | 392 void |
393 gaim_gtkdialogs_im_with_user(GaimAccount *account, const char *username) | |
9709 | 394 { |
9730 | 395 GaimConversation *conv; |
396 GaimConvWindow *win; | |
397 GaimGtkWindow *gtkwin; | |
9709 | 398 |
9753 | 399 g_return_if_fail(account != NULL); |
400 g_return_if_fail(username != NULL); | |
401 | |
9730 | 402 conv = gaim_find_conversation_with_account(username, account); |
9709 | 403 |
9730 | 404 if (conv == NULL) |
405 conv = gaim_conversation_new(GAIM_CONV_IM, account, username); | |
9709 | 406 |
9730 | 407 win = gaim_conversation_get_window(conv); |
408 gtkwin = GAIM_GTK_WINDOW(win); | |
9709 | 409 |
9730 | 410 gtk_window_present(GTK_WINDOW(gtkwin->window)); |
411 gaim_conv_window_switch_conversation(win, gaim_conversation_get_index(conv)); | |
9709 | 412 } |
413 | |
9730 | 414 static gboolean |
415 gaim_gtkdialogs_ee(const char *ee) | |
9709 | 416 { |
417 GtkWidget *window; | |
418 GtkWidget *hbox; | |
419 GtkWidget *label; | |
420 GtkWidget *img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_COOL, GTK_ICON_SIZE_DIALOG); | |
421 gchar *norm = gaim_strreplace(ee, "rocksmyworld", ""); | |
422 | |
423 label = gtk_label_new(NULL); | |
424 if (!strcmp(norm, "zilding")) | |
425 gtk_label_set_markup(GTK_LABEL(label), | |
426 "<span weight=\"bold\" size=\"large\" foreground=\"purple\">Amazing! Simply Amazing!</span>"); | |
427 else if (!strcmp(norm, "robflynn")) | |
428 gtk_label_set_markup(GTK_LABEL(label), | |
429 "<span weight=\"bold\" size=\"large\" foreground=\"#1f6bad\">Pimpin\' Penguin Style! *Waddle Waddle*</span>"); | |
430 else if (!strcmp(norm, "flynorange")) | |
431 gtk_label_set_markup(GTK_LABEL(label), | |
432 "<span weight=\"bold\" size=\"large\" foreground=\"blue\">You should be me. I'm so cute!</span>"); | |
433 else if (!strcmp(norm, "ewarmenhoven")) | |
434 gtk_label_set_markup(GTK_LABEL(label), | |
435 "<span weight=\"bold\" size=\"large\" foreground=\"orange\">Now that's what I like!</span>"); | |
436 else if (!strcmp(norm, "markster97")) | |
437 gtk_label_set_markup(GTK_LABEL(label), | |
438 "<span weight=\"bold\" size=\"large\" foreground=\"brown\">Ahh, and excellent choice!</span>"); | |
439 else if (!strcmp(norm, "seanegn")) | |
440 gtk_label_set_markup(GTK_LABEL(label), | |
441 "<span weight=\"bold\" size=\"large\" foreground=\"#009900\">Everytime you click my name, an angel gets its wings.</span>"); | |
442 else if (!strcmp(norm, "chipx86")) | |
443 gtk_label_set_markup(GTK_LABEL(label), | |
444 "<span weight=\"bold\" size=\"large\" foreground=\"red\">This sunflower seed taste like pizza.</span>"); | |
445 else if (!strcmp(norm, "markdoliner")) | |
446 gtk_label_set_markup(GTK_LABEL(label), | |
447 "<span weight=\"bold\" size=\"large\" foreground=\"#6364B1\">Hey! I was in that tumbleweed!</span>"); | |
448 else if (!strcmp(norm, "lschiere")) | |
449 gtk_label_set_markup(GTK_LABEL(label), | |
450 "<span weight=\"bold\" size=\"large\" foreground=\"gray\">I'm not anything.</span>"); | |
451 g_free(norm); | |
452 | |
453 if (strlen(gtk_label_get_label(GTK_LABEL(label))) <= 0) | |
454 return FALSE; | |
455 | |
456 window = gtk_dialog_new_with_buttons(GAIM_ALERT_TITLE, NULL, 0, GTK_STOCK_CLOSE, GTK_RESPONSE_OK, NULL); | |
457 gtk_dialog_set_default_response (GTK_DIALOG(window), GTK_RESPONSE_OK); | |
458 g_signal_connect(G_OBJECT(window), "response", G_CALLBACK(gtk_widget_destroy), NULL); | |
459 | |
460 gtk_container_set_border_width (GTK_CONTAINER(window), 6); | |
461 gtk_window_set_resizable(GTK_WINDOW(window), FALSE); | |
462 gtk_dialog_set_has_separator(GTK_DIALOG(window), FALSE); | |
463 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(window)->vbox), 12); | |
464 gtk_container_set_border_width (GTK_CONTAINER(GTK_DIALOG(window)->vbox), 6); | |
465 | |
466 hbox = gtk_hbox_new(FALSE, 12); | |
467 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window)->vbox), hbox); | |
468 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); | |
469 | |
470 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); | |
471 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | |
472 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
473 | |
474 gtk_widget_show_all(window); | |
475 return TRUE; | |
476 } | |
477 | |
478 static void | |
9730 | 479 gaim_gtkdialogs_info_cb(gpointer data, GaimRequestFields *fields) |
9709 | 480 { |
481 char *username; | |
482 gboolean found = FALSE; | |
483 GaimAccount *account; | |
484 | |
485 account = gaim_request_fields_get_account(fields, "account"); | |
486 | |
487 username = g_strdup(gaim_normalize(account, | |
488 gaim_request_fields_get_string(fields, "screenname"))); | |
489 | |
490 if (username != NULL && gaim_str_has_suffix(username, "rocksmyworld")) | |
9730 | 491 found = gaim_gtkdialogs_ee(username); |
9709 | 492 |
493 if (!found && username != NULL && *username != '\0' && account != NULL) | |
494 serv_get_info(gaim_account_get_connection(account), username); | |
495 | |
496 g_free(username); | |
497 } | |
498 | |
499 void | |
9714 | 500 gaim_gtkdialogs_info(void) |
9709 | 501 { |
502 GaimRequestFields *fields; | |
503 GaimRequestFieldGroup *group; | |
504 GaimRequestField *field; | |
505 | |
506 fields = gaim_request_fields_new(); | |
507 | |
508 group = gaim_request_field_group_new(NULL); | |
509 gaim_request_fields_add_group(fields, group); | |
510 | |
511 field = gaim_request_field_string_new("screenname", _("_Screen name"), | |
512 NULL, FALSE); | |
513 gaim_request_field_set_type_hint(field, "screenname"); | |
514 gaim_request_field_set_required(field, TRUE); | |
515 gaim_request_field_group_add_field(group, field); | |
516 | |
517 field = gaim_request_field_account_new("account", _("_Account"), NULL); | |
518 gaim_request_field_set_visible(field, | |
519 (gaim_connections_get_all() != NULL && | |
520 gaim_connections_get_all()->next != NULL)); | |
521 gaim_request_field_set_required(field, TRUE); | |
522 gaim_request_field_group_add_field(group, field); | |
523 | |
524 gaim_request_fields(gaim_get_blist(), _("Get User Info"), | |
525 NULL, | |
526 _("Please enter the screen name of the person whose " | |
527 "info you would like to view."), | |
528 fields, | |
9730 | 529 _("OK"), G_CALLBACK(gaim_gtkdialogs_info_cb), |
9709 | 530 _("Cancel"), NULL, |
531 NULL); | |
532 } | |
533 | |
534 static void | |
9730 | 535 gaim_gtkdialogs_log_cb(gpointer data, GaimRequestFields *fields) |
9709 | 536 { |
537 char *username; | |
538 GaimAccount *account; | |
539 | |
540 account = gaim_request_fields_get_account(fields, "account"); | |
541 | |
542 username = g_strdup(gaim_normalize(account, | |
543 gaim_request_fields_get_string(fields, "screenname"))); | |
544 | |
9917 | 545 if(username != NULL && *username != '\0' && account != NULL ) |
546 gaim_gtk_log_show(GAIM_LOG_IM, username, account); | |
9709 | 547 |
548 g_free(username); | |
549 } | |
550 | |
9991 | 551 /* |
552 * TODO - This needs to deal with logs of all types, not just IM logs. | |
553 */ | |
9709 | 554 void |
9714 | 555 gaim_gtkdialogs_log(void) |
9709 | 556 { |
557 GaimRequestFields *fields; | |
558 GaimRequestFieldGroup *group; | |
559 GaimRequestField *field; | |
560 | |
561 fields = gaim_request_fields_new(); | |
562 | |
563 group = gaim_request_field_group_new(NULL); | |
564 gaim_request_fields_add_group(fields, group); | |
565 | |
566 field = gaim_request_field_string_new("screenname", _("_Screen name"), | |
567 NULL, FALSE); | |
568 gaim_request_field_set_type_hint(field, "screenname"); | |
569 gaim_request_field_set_required(field, TRUE); | |
570 gaim_request_field_group_add_field(group, field); | |
571 | |
572 field = gaim_request_field_account_new("account", _("_Account"), NULL); | |
573 gaim_request_field_account_set_show_all(field, TRUE); | |
574 gaim_request_field_set_visible(field, | |
575 (gaim_accounts_get_all() != NULL && | |
576 gaim_accounts_get_all()->next != NULL)); | |
577 gaim_request_field_set_required(field, TRUE); | |
578 gaim_request_field_group_add_field(group, field); | |
579 | |
580 gaim_request_fields(gaim_get_blist(), _("Get User Log"), | |
581 NULL, | |
582 _("Please enter the screen name of the person whose " | |
583 "log you would like to view."), | |
584 fields, | |
9730 | 585 _("OK"), G_CALLBACK(gaim_gtkdialogs_log_cb), |
9709 | 586 _("Cancel"), NULL, |
587 NULL); | |
588 } | |
589 | |
9730 | 590 static void |
591 gaim_gtkdialogs_warn_cb(GtkWidget *widget, gint resp, struct warning *w) | |
9709 | 592 { |
9730 | 593 if (resp == GTK_RESPONSE_OK) |
9753 | 594 serv_warn(w->gc, w->who, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->anon))); |
9709 | 595 |
9753 | 596 dialogwindows = g_list_remove(dialogwindows, w->window); |
597 gtk_widget_destroy(w->window); | |
598 | |
9730 | 599 g_free(w->who); |
600 g_free(w); | |
9709 | 601 } |
602 | |
9753 | 603 /* |
9991 | 604 * TODO - Make this use the request API, if possible. |
9753 | 605 */ |
9730 | 606 void |
607 gaim_gtkdialogs_warn(GaimConnection *gc, const char *who) | |
9709 | 608 { |
9753 | 609 gchar *labeltext; |
9730 | 610 GtkWidget *hbox, *vbox; |
9709 | 611 GtkWidget *label; |
9753 | 612 GtkWidget *img; |
613 struct warning *w; | |
9730 | 614 |
9753 | 615 g_return_if_fail(gc != NULL); |
616 g_return_if_fail(who != NULL); | |
617 | |
618 w = g_new0(struct warning, 1); | |
9730 | 619 w->who = g_strdup(who); |
620 w->gc = gc; | |
621 | |
9753 | 622 w->window = gtk_dialog_new_with_buttons(_("Warn User"), NULL, 0, |
9730 | 623 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
624 GAIM_STOCK_WARN, GTK_RESPONSE_OK, NULL); | |
625 gtk_dialog_set_default_response (GTK_DIALOG(w->window), GTK_RESPONSE_OK); | |
626 g_signal_connect(G_OBJECT(w->window), "response", G_CALLBACK(gaim_gtkdialogs_warn_cb), w); | |
627 | |
628 gtk_container_set_border_width (GTK_CONTAINER(w->window), 6); | |
629 gtk_window_set_resizable(GTK_WINDOW(w->window), FALSE); | |
630 gtk_dialog_set_has_separator(GTK_DIALOG(w->window), FALSE); | |
631 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(w->window)->vbox), 12); | |
632 gtk_container_set_border_width (GTK_CONTAINER(GTK_DIALOG(w->window)->vbox), 6); | |
9709 | 633 |
634 hbox = gtk_hbox_new(FALSE, 12); | |
9730 | 635 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(w->window)->vbox), hbox); |
9753 | 636 |
637 img = gtk_image_new_from_stock(GAIM_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG); | |
638 gtk_misc_set_alignment(GTK_MISC(img), 0, 0); | |
9730 | 639 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); |
9709 | 640 |
9730 | 641 vbox = gtk_vbox_new(FALSE, 0); |
642 gtk_container_add(GTK_CONTAINER(hbox), vbox); | |
643 labeltext = g_strdup_printf(_("<span weight=\"bold\" size=\"larger\">Warn %s?</span>\n\n" | |
644 "This will increase %s's warning level and he or she will be subject to harsher rate limiting.\n"), who, who); | |
645 label = gtk_label_new(NULL); | |
646 gtk_label_set_markup(GTK_LABEL(label), labeltext); | |
647 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); | |
648 gtk_misc_set_alignment(GTK_MISC(label), 0, 0); | |
649 gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0); | |
650 g_free(labeltext); | |
9709 | 651 |
9730 | 652 w->anon = gtk_check_button_new_with_mnemonic(_("Warn _anonymously?")); |
653 gtk_box_pack_start(GTK_BOX(vbox), w->anon, FALSE, FALSE, 0); | |
654 | |
655 hbox = gtk_hbox_new(FALSE, 6); | |
656 gtk_container_add(GTK_CONTAINER(vbox), hbox); | |
657 img = gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_MENU); | |
658 gtk_box_pack_start(GTK_BOX(hbox), img, FALSE, FALSE, 0); | |
659 labeltext = _("<b>Anonymous warnings are less severe.</b>"); | |
660 label = gtk_label_new(NULL); | |
661 gtk_label_set_markup(GTK_LABEL(label), labeltext); | |
662 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); | |
9709 | 663 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); |
664 | |
9730 | 665 dialogwindows = g_list_prepend(dialogwindows, w->window); |
666 gtk_widget_show_all(w->window); | |
9709 | 667 } |
668 | |
669 static void | |
9730 | 670 gaim_gtkdialogs_alias_contact_cb(GaimContact *contact, const char *new_alias) |
671 { | |
672 gaim_contact_set_alias(contact, new_alias); | |
673 } | |
674 | |
675 void | |
676 gaim_gtkdialogs_alias_contact(GaimContact *contact) | |
677 { | |
9753 | 678 g_return_if_fail(contact != NULL); |
679 | |
9730 | 680 gaim_request_input(NULL, _("Alias Contact"), NULL, |
681 _("Enter an alias for this contact."), | |
682 contact->alias, FALSE, FALSE, NULL, | |
683 _("Alias"), G_CALLBACK(gaim_gtkdialogs_alias_contact_cb), | |
684 _("Cancel"), NULL, contact); | |
685 } | |
686 | |
687 static void | |
688 gaim_gtkdialogs_alias_buddy_cb(GaimBuddy *buddy, const char *new_alias) | |
689 { | |
690 gaim_blist_alias_buddy(buddy, new_alias); | |
691 serv_alias_buddy(buddy); | |
692 } | |
693 | |
694 void | |
9753 | 695 gaim_gtkdialogs_alias_buddy(GaimBuddy *buddy) |
9730 | 696 { |
9753 | 697 gchar *secondary; |
698 | |
699 g_return_if_fail(buddy != NULL); | |
700 | |
701 secondary = g_strdup_printf(_("Enter an alias for %s."), buddy->name); | |
9730 | 702 |
703 gaim_request_input(NULL, _("Alias Buddy"), NULL, | |
9753 | 704 secondary, buddy->alias, FALSE, FALSE, NULL, |
9730 | 705 _("Alias"), G_CALLBACK(gaim_gtkdialogs_alias_buddy_cb), |
9753 | 706 _("Cancel"), NULL, buddy); |
9730 | 707 |
708 g_free(secondary); | |
709 } | |
710 | |
711 static void | |
712 gaim_gtkdialogs_alias_chat_cb(GaimChat *chat, const char *new_alias) | |
9709 | 713 { |
714 gaim_blist_alias_chat(chat, new_alias); | |
715 } | |
716 | |
717 void | |
9730 | 718 gaim_gtkdialogs_alias_chat(GaimChat *chat) |
9709 | 719 { |
9753 | 720 g_return_if_fail(chat != NULL); |
721 | |
9709 | 722 gaim_request_input(NULL, _("Alias Chat"), NULL, |
723 _("Enter an alias for this chat."), | |
724 chat->alias, FALSE, FALSE, NULL, | |
9730 | 725 _("Alias"), G_CALLBACK(gaim_gtkdialogs_alias_chat_cb), |
9709 | 726 _("Cancel"), NULL, chat); |
727 } | |
728 | |
729 static void | |
9753 | 730 gaim_gtkdialogs_remove_contact_cb(GaimContact *contact) |
9709 | 731 { |
9730 | 732 GaimBlistNode *bnode, *cnode; |
733 GaimGroup *group; | |
734 | |
735 cnode = (GaimBlistNode *)contact; | |
736 group = (GaimGroup*)cnode->parent; | |
737 for (bnode = cnode->child; bnode; bnode = bnode->next) { | |
738 GaimBuddy *buddy = (GaimBuddy*)bnode; | |
739 if (gaim_account_is_connected(buddy->account)) | |
740 serv_remove_buddy(buddy->account->gc, buddy, group); | |
741 } | |
742 gaim_blist_remove_contact(contact); | |
743 } | |
744 | |
745 void | |
746 gaim_gtkdialogs_remove_contact(GaimContact *contact) | |
747 { | |
748 GaimBuddy *buddy = gaim_contact_get_priority_buddy(contact); | |
749 | |
9753 | 750 g_return_if_fail(contact != NULL); |
751 g_return_if_fail(buddy != NULL); | |
9730 | 752 |
753 if (((GaimBlistNode*)contact)->child == (GaimBlistNode*)buddy && | |
754 !((GaimBlistNode*)buddy)->next) { | |
755 gaim_gtkdialogs_remove_buddy(buddy); | |
756 } else { | |
9753 | 757 gchar *text = g_strdup_printf(_("You are about to remove the contact containing %s and %d other buddies from your buddy list. Do you want to continue?"), |
9730 | 758 buddy->name, contact->totalsize - 1); |
759 | |
9976 | 760 gaim_request_action(NULL, NULL, _("Remove Contact"), text, 0, contact, 2, |
9753 | 761 _("Remove Contact"), G_CALLBACK(gaim_gtkdialogs_remove_contact_cb), |
9730 | 762 _("Cancel"), NULL); |
763 | |
764 g_free(text); | |
765 } | |
9709 | 766 } |
767 | |
768 void | |
9753 | 769 gaim_gtkdialogs_remove_group_cb(GaimGroup *group) |
9709 | 770 { |
9730 | 771 GaimBlistNode *cnode, *bnode; |
772 | |
773 cnode = ((GaimBlistNode*)group)->child; | |
774 | |
775 while (cnode) { | |
776 if (GAIM_BLIST_NODE_IS_CONTACT(cnode)) { | |
777 bnode = cnode->child; | |
778 cnode = cnode->next; | |
779 while (bnode) { | |
780 GaimBuddy *buddy; | |
781 if (GAIM_BLIST_NODE_IS_BUDDY(bnode)) { | |
782 GaimConversation *conv; | |
783 buddy = (GaimBuddy*)bnode; | |
784 bnode = bnode->next; | |
785 conv = gaim_find_conversation_with_account(buddy->name, buddy->account); | |
786 if (gaim_account_is_connected(buddy->account)) { | |
787 serv_remove_buddy(buddy->account->gc, buddy, group); | |
788 gaim_blist_remove_buddy(buddy); | |
789 if (conv) | |
790 gaim_conversation_update(conv, | |
791 GAIM_CONV_UPDATE_REMOVE); | |
792 } | |
793 } else { | |
794 bnode = bnode->next; | |
795 } | |
796 } | |
797 } else if (GAIM_BLIST_NODE_IS_CHAT(cnode)) { | |
798 GaimChat *chat = (GaimChat *)cnode; | |
799 cnode = cnode->next; | |
800 if (gaim_account_is_connected(chat->account)) | |
801 gaim_blist_remove_chat(chat); | |
802 } else { | |
803 cnode = cnode->next; | |
804 } | |
805 } | |
806 | |
807 gaim_blist_remove_group(group); | |
808 } | |
809 | |
810 void | |
811 gaim_gtkdialogs_remove_group(GaimGroup *group) | |
812 { | |
9753 | 813 gchar *text; |
814 | |
815 g_return_if_fail(group != NULL); | |
816 | |
817 text = g_strdup_printf(_("You are about to remove the group %s and all its members from your buddy list. Do you want to continue?"), | |
818 group->name); | |
9730 | 819 |
9976 | 820 gaim_request_action(NULL, NULL, _("Remove Group"), text, 0, group, 2, |
9753 | 821 _("Remove Group"), G_CALLBACK(gaim_gtkdialogs_remove_group_cb), |
9730 | 822 _("Cancel"), NULL); |
823 | |
824 g_free(text); | |
9709 | 825 } |
826 | |
827 static void | |
9753 | 828 gaim_gtkdialogs_remove_buddy_cb(GaimBuddy *buddy) |
9709 | 829 { |
9730 | 830 GaimGroup *group; |
831 GaimConversation *conv; | |
832 gchar *name; | |
833 GaimAccount *account; | |
834 | |
835 group = gaim_find_buddys_group(buddy); | |
836 name = g_strdup(buddy->name); /* b->name is a crasher after remove_buddy */ | |
837 account = buddy->account; | |
838 | |
9753 | 839 gaim_debug_info("blist", "Removing '%s' from buddy list.\n", buddy->name); |
9991 | 840 /* TODO - Should remove from blist first... then call serv_remove_buddy()? */ |
9730 | 841 serv_remove_buddy(buddy->account->gc, buddy, group); |
842 gaim_blist_remove_buddy(buddy); | |
843 | |
844 conv = gaim_find_conversation_with_account(name, account); | |
845 | |
846 if (conv != NULL) | |
847 gaim_conversation_update(conv, GAIM_CONV_UPDATE_REMOVE); | |
848 | |
849 g_free(name); | |
9709 | 850 } |
851 | |
852 void | |
9730 | 853 gaim_gtkdialogs_remove_buddy(GaimBuddy *buddy) |
9709 | 854 { |
9753 | 855 gchar *text; |
9730 | 856 |
9753 | 857 g_return_if_fail(buddy != NULL); |
9730 | 858 |
9753 | 859 text = g_strdup_printf(_("You are about to remove %s from your buddy list. Do you want to continue?"), |
860 buddy->name); | |
9730 | 861 |
9976 | 862 gaim_request_action(NULL, NULL, _("Remove Buddy"), text, 0, buddy, 2, |
9753 | 863 _("Remove Buddy"), G_CALLBACK(gaim_gtkdialogs_remove_buddy_cb), |
9730 | 864 _("Cancel"), NULL); |
865 | |
866 g_free(text); | |
867 } | |
9709 | 868 |
9730 | 869 static void |
9753 | 870 gaim_gtkdialogs_remove_chat_cb(GaimChat *chat) |
9730 | 871 { |
9918 | 872 char *name = NULL; |
873 GaimConversation *conv = NULL; | |
874 | |
875 if (GAIM_PLUGIN_PROTOCOL_INFO(chat->account->gc->prpl)->get_chat_name != NULL) | |
876 name = GAIM_PLUGIN_PROTOCOL_INFO(chat->account->gc->prpl)->get_chat_name(chat->components); | |
877 | |
9730 | 878 gaim_blist_remove_chat(chat); |
9918 | 879 |
880 if (name != NULL) { | |
881 conv = gaim_find_conversation_with_account(name, chat->account); | |
882 g_free(name); | |
883 } | |
884 | |
885 if (conv != NULL) | |
886 gaim_conversation_update(conv, GAIM_CONV_UPDATE_REMOVE); | |
9730 | 887 } |
9709 | 888 |
9730 | 889 void |
890 gaim_gtkdialogs_remove_chat(GaimChat *chat) | |
891 { | |
9753 | 892 gchar *name = gaim_chat_get_display_name(chat); |
893 gchar *text = g_strdup_printf(_("You are about to remove the chat %s from your buddy list. Do you want to continue?"), name); | |
894 | |
895 g_return_if_fail(chat != NULL); | |
9730 | 896 |
9976 | 897 gaim_request_action(NULL, NULL, _("Remove Chat"), text, 0, chat, 2, |
9753 | 898 _("Remove Chat"), G_CALLBACK(gaim_gtkdialogs_remove_chat_cb), |
9730 | 899 _("Cancel"), NULL); |
900 | |
901 g_free(name); | |
902 g_free(text); | |
9709 | 903 } |