1 /* Bluefish HTML Editor
2 * snippets_wizard.c - plugin for snippets sidebar
3 *
4 * Copyright (C) 2006,2009-2011 Olivier Sessink
5 *
6 * This program 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 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 /*#define DEBUG*/
20
21 #include <string.h>
22
23 #include "snippets.h"
24 #include "snippets_load.h"
25 #include "snippets_leaf_insert.h"
26 #include "snippets_leaf_snr.h"
27 #include "../gtk_easy.h"
28 #include "../dialog_utils.h"
29
30 typedef enum {
31 page_type, /* 0 */
32 page_name,
33 page_branch,
34 page_insert,
35 page_snr,
36 page_finished
37 } Tpagenum;
38
39 typedef struct {
40 Tsnippetswin *snw;
41 GtkWidget *dialog;
42 gint choice;
43 gchar *name;
44 gchar *description;
45 gpointer pagestruct;
46 Tpagenum pagenum;
47 xmlNodePtr node;
48 } Tsnipwiz;
49
get_parentbranch(Tsnippetswin * snw,GtkTreePath ** parentp,xmlNodePtr * parentn)50 static void get_parentbranch(Tsnippetswin *snw, GtkTreePath **parentp, xmlNodePtr *parentn) {
51 if (snw->lastclickedpath) {
52 *parentp = gtk_tree_path_copy(snw->lastclickedpath);
53 } else {
54 *parentp = NULL;
55 }
56 if (snw->lastclickednode) {
57 if (xmlStrEqual(snw->lastclickednode->name, (const xmlChar *)"leaf")) {
58 *parentn = snw->lastclickednode->parent;
59 if (*parentp) {
60 if (!gtk_tree_path_up(*parentp)) {
61 gtk_tree_path_free(*parentp);
62 *parentp = NULL;
63 }
64 }
65 } else {
66 *parentn = snw->lastclickednode;
67 }
68 } else { /* parent must be the root element <snippets> */
69 *parentn = xmlDocGetRootElement(snippets_v.doc);
70 }
71 }
72
add_item_to_tree(GtkTreePath * parentp,gint pixmaptype,const gchar * name,gpointer ptr)73 static void add_item_to_tree(GtkTreePath *parentp, gint pixmaptype, const gchar *name, gpointer ptr) {
74 GtkTreeIter citer;
75 if (parentp) {
76 GtkTreeIter piter;
77 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(snippets_v.store),&piter,parentp)) {
78 gtk_tree_store_append(GTK_TREE_STORE(snippets_v.store), &citer, &piter);
79 snippets_fill_tree_item_from_node(&citer, ptr);
80 } else {
81 g_print("hmm weird error!?!\n");
82 }
83 } else {
84 gtk_tree_store_append(GTK_TREE_STORE(snippets_v.store), &citer, NULL);
85 snippets_fill_tree_item_from_node(&citer, ptr);
86 }
87 }
88
update_name_in_tree(Tsnippetswin * snw,const gchar * name)89 static void update_name_in_tree(Tsnippetswin *snw, const gchar *name) {
90 if (snw->lastclickedpath) {
91 GtkTreeIter citer;
92 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(snippets_v.store),&citer,snw->lastclickedpath)) {
93 gtk_tree_store_set(snippets_v.store, &citer, TITLE_COLUMN, name,-1);
94 }
95 }
96 }
97
98 typedef struct {
99 GtkWidget *table;
100 GtkWidget *entries[6];
101 GtkWidget *matchtype;
102 GtkWidget *scope;
103 GtkWidget *casesens;
104 GtkWidget *escapechars;
105 GtkWidget *searchpat;
106 GtkWidget *replace;
107 } TpageSnr;
108
snippets_build_pageSnr(Tsnipwiz * snwiz,GtkWidget * dialog_action)109 static gpointer snippets_build_pageSnr(Tsnipwiz *snwiz, GtkWidget *dialog_action) {
110 const gchar *scope[] = {
111 N_("Entire document"),
112 N_("Forward from cursor position"),
113 N_("Selection"),
114 N_("All open files"),
115 };
116
117 const gchar *matchPattern[] = {
118 N_("Normal"),
119 N_("PERL")
120 };
121 GtkWidget *label;
122 gint i;
123 TpageSnr *p = g_new(TpageSnr,1);
124
125 p->table = gtk_table_new(8, 4, FALSE);
126 gtk_table_set_row_spacings(GTK_TABLE (p->table), 6);
127 gtk_table_set_col_spacings(GTK_TABLE (p->table), 12);
128 gtk_box_pack_start(GTK_BOX(dialog_action), p->table, TRUE, TRUE, 0);
129
130 label = gtk_label_new(_("Specify a search and a replace pattern. You may use %0, %1, ...%5 placeholders to ask for values when you activate this item. Give these placeholders an appropriate name on the right. (Please use %% if you need literal % in your string!)"));
131 /*gtk_label_set_use_markup(GTK_LABEL(label),TRUE);*/
132 #if GTK_CHECK_VERSION(3,2,0)
133 gtk_label_set_width_chars(GTK_LABEL(label),50);
134 #endif
135 gtk_label_set_line_wrap(GTK_LABEL(label),TRUE);
136 gtk_table_attach(GTK_TABLE(p->table),label, 0,4,0,1
137 ,GTK_FILL,GTK_FILL,0,0);
138
139 p->searchpat = gtk_entry_new();
140 dialog_mnemonic_label_in_table(_("_Search for: "), p->searchpat, p->table, 0, 1, 1, 2);
141 gtk_table_attach(GTK_TABLE(p->table),p->searchpat, 1,4,1,2,GTK_FILL|GTK_EXPAND,GTK_FILL,0,0);
142
143 p->replace = gtk_entry_new();
144 dialog_mnemonic_label_in_table(_("Replace _with: "), p->replace, p->table, 0, 1, 2, 3);
145 gtk_table_attach(GTK_TABLE(p->table),p->replace, 1,4,2,3,GTK_FILL|GTK_EXPAND,GTK_FILL,0,0);
146
147 p->scope = gtk_combo_box_text_new();
148 for (i = 0; i < G_N_ELEMENTS(scope); i++) {
149 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(p->scope), _(scope[i]));
150 }
151 dialog_mnemonic_label_in_table(_("Sco_pe: "), p->scope, p->table, 0, 1, 3, 4);
152 gtk_table_attach(GTK_TABLE(p->table),p->scope, 1,2,3,4,GTK_FILL|GTK_EXPAND,GTK_SHRINK,0,0);
153
154 p->matchtype = gtk_combo_box_text_new();
155 for (i = 0; i < G_N_ELEMENTS(matchPattern); i++) {
156 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(p->matchtype), _(matchPattern[i]));
157 }
158 dialog_mnemonic_label_in_table(_("Match Patter_n: "), p->matchtype, p->table, 0, 1, 4, 5);
159 gtk_table_attach(GTK_TABLE(p->table), p->matchtype, 1, 2, 4, 5, GTK_EXPAND|GTK_FILL,GTK_SHRINK, 0, 0);
160
161 p->casesens = gtk_check_button_new_with_mnemonic(_("Case sensitive _matching"));
162 gtk_widget_set_tooltip_text(p->casesens,_("Only match if case (upper/lower) is identical."));
163 gtk_table_attach(GTK_TABLE(p->table), p->casesens, 0, 2, 5, 6, GTK_EXPAND|GTK_FILL,GTK_SHRINK, 0, 0);
164
165 p->escapechars = gtk_check_button_new_with_mnemonic(_("_Use escape chars"));
166 gtk_widget_set_tooltip_text(p->escapechars,_("Unescape backslash escaped characters such as \\n, \\t etc."));
167 gtk_table_attach(GTK_TABLE(p->table), p->escapechars, 0, 2, 6, 7, GTK_EXPAND|GTK_FILL,GTK_SHRINK, 0, 0);
168
169 for (i = 0; i < 6; i++) {
170 gchar *tmpstr;
171 tmpstr = g_strdup_printf("%%%d ", i);
172 label = gtk_label_new(tmpstr);
173 gtk_misc_set_alignment(GTK_MISC(label),1,0.5);
174 gtk_table_attach(GTK_TABLE(p->table),label, 2,3,i+3,i+4
175 ,GTK_FILL,GTK_FILL,0,0);
176 g_free(tmpstr);
177 p->entries[i] = gtk_entry_new();
178 gtk_table_attach(GTK_TABLE(p->table),p->entries[i], 3,4,i+3,i+4
179 ,GTK_FILL,GTK_FILL,0,0);
180 }
181
182 if (snwiz->node) {
183 xmlNodePtr cur;
184 xmlChar *tmpstr;
185 xmlChar *region,*matchtype,*casesens,*escapechars;
186 gint i=0;
187 for (cur = snwiz->node->xmlChildrenNode;cur != NULL;cur = cur->next) {
188 if (i < 6 && xmlStrEqual(cur->name, (const xmlChar *)"param")) {
189 xmlChar *name;
190 name = xmlGetProp(cur, (const xmlChar *)"name");
191 gtk_entry_set_text(GTK_ENTRY(p->entries[i]), (gchar *)name);
192 g_free(name);
193 i++;
194 } else if (xmlStrEqual(cur->name, (const xmlChar *)"searchpat")) {
195 tmpstr = xmlNodeListGetString(snippets_v.doc, cur->xmlChildrenNode, 1);
196 DEBUG_MSG("searchpattern: %s\n",tmpstr);
197 gtk_entry_set_text(GTK_ENTRY(p->searchpat),(gchar *)tmpstr);
198 g_free(tmpstr);
199 } else if (xmlStrEqual(cur->name, (const xmlChar *)"replacepat")) {
200 tmpstr = xmlNodeListGetString(snippets_v.doc, cur->xmlChildrenNode, 1);
201 DEBUG_MSG("replacepattern: %s\n",tmpstr);
202 gtk_entry_set_text(GTK_ENTRY(p->replace),(gchar *)tmpstr);
203 g_free(tmpstr);
204 }
205 }
206 region = xmlGetProp(snwiz->node, (const xmlChar *)"region");
207 matchtype = xmlGetProp(snwiz->node, (const xmlChar *)"matchtype");
208 casesens = xmlGetProp(snwiz->node, (const xmlChar *)"casesens");
209 escapechars = xmlGetProp(snwiz->node, (const xmlChar *)"escapechars");
210 gtk_combo_box_set_active(GTK_COMBO_BOX(p->scope),snippets_snr_region_from_char(region));
211 gtk_combo_box_set_active(GTK_COMBO_BOX(p->matchtype),snippets_snr_matchtype_from_char(matchtype));
212 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p->casesens), (casesens && casesens[0] == '1'));
213 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p->escapechars), (escapechars && escapechars[0] == '1'));
214 } else {
215 gtk_combo_box_set_active(GTK_COMBO_BOX(p->scope),0);
216 gtk_combo_box_set_active(GTK_COMBO_BOX(p->matchtype),0);
217 }
218
219 gtk_widget_show_all(p->table);
220 return p;
221 }
snippets_delete_pageSnr(Tsnipwiz * snwiz,gpointer data)222 static void snippets_delete_pageSnr(Tsnipwiz *snwiz, gpointer data) {
223 TpageSnr *p = (TpageSnr *)data;
224 gtk_widget_destroy(p->table);
225 g_free(p);
226 }
227
snippets_test_pageSnr(Tsnipwiz * snwiz,gpointer data)228 static gint snippets_test_pageSnr(Tsnipwiz *snwiz, gpointer data) {
229 TpageSnr *p = (TpageSnr *)data;
230 GtkTreePath *parentp;
231 xmlNodePtr parentn, childn, tmpn;
232 gchar *tmp="",*search,*replace;
233 gint i;
234 gint scope,casesens,matchtype,escapechars;
235
236 scope = gtk_combo_box_get_active(GTK_COMBO_BOX(p->scope));
237 matchtype = gtk_combo_box_get_active(GTK_COMBO_BOX(p->matchtype));
238 casesens = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p->casesens));
239 escapechars = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p->escapechars));
240
241 if (snwiz->node) {
242 xmlNodePtr cur;
243 /* clean the old one */
244 childn = snwiz->node;
245 cur = childn->xmlChildrenNode;
246 while (cur) {
247 xmlUnlinkNode(cur);
248 xmlFreeNode(cur);
249 cur = childn->xmlChildrenNode;
250 }
251 } else {
252 /* find the branch to add this leaf to */
253 get_parentbranch(snwiz->snw, &parentp, &parentn);
254 /* build a new one */
255 childn = xmlNewChild(parentn,NULL,(const xmlChar *)"leaf",NULL);
256 xmlSetProp(childn, (const xmlChar *)"type", (const xmlChar *)"snr");
257 }
258
259 /* build the leaf */
260 xmlSetProp(childn, (const xmlChar *)"title", (const xmlChar *)snwiz->name);
261 if (snwiz->description) {
262 xmlSetProp(childn, (const xmlChar *)"tooltip", (const xmlChar *)snwiz->description);
263 }
264
265 switch (scope) {
266 case 1:
267 tmp = "c";
268 break;
269 case 2:
270 tmp = "s";
271 break;
272 case 3:
273 tmp = "a";
274 break;
275 case 0:
276 tmp = "b";
277 break;
278 }
279 xmlSetProp(childn, (const xmlChar *)"region", (const xmlChar *) tmp);
280 switch (matchtype) {
281 case 0:
282 tmp = "normal";
283 break;
284 case 1:
285 tmp = "perl";
286 break;
287 }
288 xmlSetProp(childn, (const xmlChar *)"matchtype", (const xmlChar *) tmp);
289
290 xmlSetProp(childn, (const xmlChar *)"casesens", casesens ? (const xmlChar *)"1": (const xmlChar *)"0");
291 xmlSetProp(childn, (const xmlChar *)"escapechars", escapechars ? (const xmlChar *)"1": (const xmlChar *)"0");
292
293 search = gtk_editable_get_chars(GTK_EDITABLE(p->searchpat),0,-1);
294 replace = gtk_editable_get_chars(GTK_EDITABLE(p->replace),0,-1);
295 xmlNewTextChild(childn,NULL,(const xmlChar *)"searchpat",(const xmlChar *)search);
296 xmlNewTextChild(childn,NULL,(const xmlChar *)"replacepat",(const xmlChar *)replace);
297 for (i = 0; i < 6; i++) {
298 gchar *tmpstr;
299 tmpstr = gtk_editable_get_chars(GTK_EDITABLE(p->entries[i]),0,-1);
300 if (strlen(tmpstr)>0) {
301 tmpn = xmlNewChild(childn,NULL,(const xmlChar *)"param", NULL);
302 xmlSetProp(tmpn, (const xmlChar *)"name", (const xmlChar *)tmpstr);
303 }
304 }
305 if (!snwiz->node) {
306 /* now add this item to the treestore */
307 add_item_to_tree(parentp, pixmap_type_snr, snwiz->name, childn);
308 } else {
309 update_name_in_tree(snwiz->snw, snwiz->name);
310 }
311 return page_finished;
312 }
313
314 typedef struct {
315 GtkWidget *table;
316 GtkWidget *entries[10];
317 GtkWidget *is_file[10];
318 GtkWidget *before_v;
319 GtkWidget *after_v;
320 GtkTextBuffer *before;
321 GtkTextBuffer *after;
322 } TpageInsert;
323
snippets_build_pageInsert(Tsnipwiz * snwiz,GtkWidget * dialog_action)324 static gpointer snippets_build_pageInsert(Tsnipwiz *snwiz, GtkWidget *dialog_action) {
325 GtkWidget *scrolwin, *label;
326 gint i;
327 gchar *tmpstr;
328 TpageInsert *p2 = g_new(TpageInsert,1);
329
330 p2->table = gtk_table_new(13, 5, FALSE);
331 gtk_table_set_row_spacings(GTK_TABLE (p2->table), 6);
332 gtk_table_set_col_spacings(GTK_TABLE (p2->table), 12);
333 gtk_box_pack_start(GTK_BOX(dialog_action), p2->table, TRUE, TRUE, 0);
334
335 label = gtk_label_new(_("The <i>before</i> text will be inserted before the cursor position or the current selection, the <i>after</i> text will be inserted after the cursor position or the current selection. You may use %0, %1, ...%9 placeholders to ask for values when you activate this item. Give these placeholders an appropriate name on the right. (Please use %% if you need literal % in your string!)"));
336 gtk_label_set_use_markup(GTK_LABEL(label),TRUE);
337 gtk_label_set_line_wrap(GTK_LABEL(label),TRUE);
338 #if GTK_CHECK_VERSION(3,2,0)
339 gtk_label_set_width_chars(GTK_LABEL(label),50);
340 #endif
341 gtk_table_attach(GTK_TABLE(p2->table),label, 0,5,0,1
342 ,GTK_FILL|GTK_EXPAND,GTK_FILL,0,0);
343
344 label = gtk_label_new(_("<i>Before</i> text"));
345 gtk_label_set_use_markup(GTK_LABEL(label),TRUE);
346 gtk_misc_set_alignment(GTK_MISC(label),0,0.5);
347 gtk_table_attach(GTK_TABLE(p2->table),label, 0,1,1,2,GTK_FILL,GTK_FILL,0,0);
348 scrolwin = textview_buffer_in_scrolwin(&p2->before_v, -1, -1, NULL, GTK_WRAP_NONE);
349 gtk_table_attach(GTK_TABLE(p2->table), scrolwin, /*left*/0,/*right*/1,/*top*/2,/*bottom*/6
350 ,/*xoptions*/GTK_EXPAND|GTK_FILL,/*yoptions*/GTK_EXPAND|GTK_FILL
351 ,/*xpadding*/0,/*ypadding*/0);
352 p2->before = gtk_text_view_get_buffer(GTK_TEXT_VIEW(p2->before_v));
353
354 label = gtk_label_new(_("<i>After</i> text"));
355 gtk_label_set_use_markup(GTK_LABEL(label),TRUE);
356 gtk_misc_set_alignment(GTK_MISC(label),0,0.5);
357 gtk_table_attach(GTK_TABLE(p2->table),label, 0,1,6,7,GTK_FILL,GTK_FILL,0,0);
358 scrolwin = textview_buffer_in_scrolwin(&p2->after_v, -1, -1, NULL, GTK_WRAP_NONE);
359 gtk_table_attach(GTK_TABLE(p2->table), scrolwin, 0,1,7,11
360 ,GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL,0,0);
361 p2->after = gtk_text_view_get_buffer(GTK_TEXT_VIEW(p2->after_v));
362 gtk_table_attach(GTK_TABLE(p2->table),gtk_label_new(_("Number")), 1,2,1,2
363 ,GTK_FILL,GTK_FILL,0,0);
364 gtk_table_attach(GTK_TABLE(p2->table),gtk_label_new(_("Name")), 2,3,1,2
365 ,GTK_FILL,GTK_FILL,0,0);
366 gtk_table_attach(GTK_TABLE(p2->table),gtk_label_new(_("Is file path")), 3,4,1,2
367 ,GTK_FILL,GTK_FILL,0,0);
368 for (i = 0; i < 10; i++) {
369 tmpstr = g_strdup_printf("%%%d ", i);
370 label = gtk_label_new(tmpstr);
371 gtk_misc_set_alignment(GTK_MISC(label),1,0.5);
372 gtk_table_attach(GTK_TABLE(p2->table),label, 1,2,i+2,i+3
373 ,GTK_FILL,GTK_FILL,0,0);
374 g_free(tmpstr);
375 p2->entries[i] = gtk_entry_new();
376 gtk_table_attach(GTK_TABLE(p2->table),p2->entries[i], 2,3,i+2,i+3
377 ,GTK_FILL,GTK_FILL,0,0);
378 p2->is_file[i] = gtk_check_button_new();
379 gtk_table_attach(GTK_TABLE(p2->table),p2->is_file[i], 3,4,i+2,i+3
380 ,GTK_SHRINK,GTK_SHRINK,0,0);
381 }
382
383 if (snwiz->node) {
384 xmlNodePtr cur;
385 xmlChar *tmpstr;
386 gint i=0;
387 for (cur = snwiz->node->xmlChildrenNode;cur != NULL;cur = cur->next) {
388 if (i<10 && xmlStrEqual(cur->name, (const xmlChar *)"param")) {
389 xmlChar *name, *is_file;
390 name = xmlGetProp(cur, (const xmlChar *)"name");
391 is_file = xmlGetProp(cur, (const xmlChar *)"is_file");
392 gtk_entry_set_text(GTK_ENTRY(p2->entries[i]), (gchar *)name);
393 if (is_file&&is_file[0]=='1')
394 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p2->is_file[i]),1);
395 g_free(name);
396 g_free(is_file);
397 i++;
398 } else if (xmlStrEqual(cur->name, (const xmlChar *)"before")) {
399 tmpstr = xmlNodeListGetString(snippets_v.doc, cur->xmlChildrenNode, 1);
400 if (tmpstr) {
401 gtk_text_buffer_set_text(p2->before,(gchar *)tmpstr,-1);
402 g_free(tmpstr);
403 }
404 } else if (xmlStrEqual(cur->name, (const xmlChar *)"after")) {
405 tmpstr = xmlNodeListGetString(snippets_v.doc, cur->xmlChildrenNode, 1);
406 if (tmpstr) {
407 gtk_text_buffer_set_text(p2->after,(gchar *)tmpstr,-1);
408 g_free(tmpstr);
409 }
410 }
411 }
412 }
413 gtk_widget_show_all(p2->table);
414 return p2;
415 }
416
snippets_delete_pageInsert(Tsnipwiz * snwiz,gpointer data)417 static void snippets_delete_pageInsert(Tsnipwiz *snwiz, gpointer data) {
418 TpageInsert *p2 = (TpageInsert *)data;
419 gtk_widget_destroy(p2->table);
420 g_free(p2);
421 }
422
snippets_test_pageInsert(Tsnipwiz * snwiz,gpointer data)423 static gint snippets_test_pageInsert(Tsnipwiz *snwiz, gpointer data) {
424 TpageInsert *p2 = (TpageInsert *)data;
425 GtkTreePath *parentp;
426 xmlNodePtr parentn, childn, tmpn;
427 gchar *before, *after;
428 gint i;
429
430 if (snwiz->node) {
431 xmlNodePtr cur;
432 /* clean the old one */
433 childn = snwiz->node;
434 cur = childn->xmlChildrenNode;
435 while (cur) {
436 xmlUnlinkNode(cur);
437 xmlFreeNode(cur);
438 cur = childn->xmlChildrenNode;
439 }
440 } else {
441 /* find the branch to add this leaf to */
442 get_parentbranch(snwiz->snw, &parentp, &parentn);
443 /* build a new one */
444 childn = xmlNewChild(parentn,NULL,(const xmlChar *)"leaf",NULL);
445 xmlSetProp(childn, (const xmlChar *)"type", (const xmlChar *)"insert");
446 }
447
448 /* build the leaf */
449 before = textbuffer_get_all_chars(p2->before);
450 after = textbuffer_get_all_chars(p2->after);
451 xmlSetProp(childn, (const xmlChar *)"title", (const xmlChar *)snwiz->name);
452 if (snwiz->description) {
453 xmlSetProp(childn, (const xmlChar *)"tooltip", (const xmlChar *)snwiz->description);
454 }
455
456 xmlNewTextChild(childn,NULL,(const xmlChar *)"before",(const xmlChar *)before);
457 xmlNewTextChild(childn,NULL,(const xmlChar *)"after",(const xmlChar *)after);
458 for (i = 0; i < 10; i++) {
459 gchar *tmpstr;
460 tmpstr = gtk_editable_get_chars(GTK_EDITABLE(p2->entries[i]),0,-1);
461 if (strlen(tmpstr)>0) {
462 tmpn = xmlNewChild(childn,NULL,(const xmlChar *)"param", NULL);
463 xmlSetProp(tmpn, (const xmlChar *)"name", (const xmlChar *)tmpstr);
464 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p2->is_file[i]))) {
465 xmlSetProp(tmpn, (const xmlChar *)"is_file", (const xmlChar *)"1");
466 }
467 }
468 }
469 if (!snwiz->node) {
470 /* now add this item to the treestore */
471 add_item_to_tree(parentp, pixmap_type_insert, snwiz->name, childn);
472 } else {
473 update_name_in_tree(snwiz->snw, snwiz->name);
474 }
475 return page_finished;
476 }
477
478 typedef struct {
479 GtkWidget *entry;
480 GtkWidget *vbox;
481 } TpageBranch;
482
snippets_build_pageBranch(Tsnipwiz * snwiz,GtkWidget * dialog_action)483 static gpointer snippets_build_pageBranch(Tsnipwiz *snwiz, GtkWidget *dialog_action) {
484 GtkWidget *label;
485 gchar *namestr=NULL;
486 TpageBranch *p1 = g_new(TpageBranch,1);
487 if (snwiz->node) { /* we're editing a node! */
488 namestr = (gchar *)xmlGetProp(snwiz->node, (const xmlChar *)"title");
489 }
490 p1->vbox = gtk_vbox_new(TRUE,12);
491 gtk_container_add(GTK_CONTAINER(dialog_action),p1->vbox);
492 label = gtk_label_new(_("Enter the name of the branch:"));
493 gtk_box_pack_start(GTK_BOX(p1->vbox),label,TRUE,TRUE,12);
494 p1->entry = gtk_entry_new();
495 if (namestr) {
496 gtk_entry_set_text((GtkEntry *)p1->entry,namestr);
497 }
498 gtk_box_pack_start(GTK_BOX(p1->vbox),p1->entry,TRUE,TRUE,12);
499 gtk_widget_show_all(p1->vbox);
500 return p1;
501 }
502
snippets_delete_pageBranch(Tsnipwiz * snwiz,gpointer data)503 static void snippets_delete_pageBranch(Tsnipwiz *snwiz, gpointer data) {
504 TpageBranch *p1 = (TpageBranch *)data;
505 gtk_widget_destroy(p1->vbox);
506 }
507
snippets_test_pageBranch(Tsnipwiz * snwiz,gpointer data)508 static gint snippets_test_pageBranch(Tsnipwiz *snwiz, gpointer data) {
509 TpageBranch *p1 = (TpageBranch *)data;
510 gchar *name;
511 GtkTreePath *parentp=NULL;
512 xmlNodePtr parent=NULL, child;
513 GtkTreeIter piter, citer;
514
515 name = gtk_editable_get_chars(GTK_EDITABLE(p1->entry),0,-1);
516
517 if (snwiz->node) {
518 xmlSetProp(snwiz->node, (const xmlChar *)"title", (const xmlChar *)name);
519 update_name_in_tree(snwiz->snw, name);
520 } else {
521 /* lets build the branch! */
522 if (snwiz->snw->lastclickedpath) {
523 parentp = gtk_tree_path_copy(snwiz->snw->lastclickedpath);
524 }
525 if (snwiz->snw->lastclickednode) {
526 if (xmlStrEqual(snwiz->snw->lastclickednode->name, (const xmlChar *)"leaf")) {
527 DEBUG_MSG("clicked node was a leaf\n");
528 parent = snwiz->snw->lastclickednode->parent;
529 if (parentp) {
530 if (!gtk_tree_path_up(parentp)) {
531 DEBUG_MSG("could not go up, set parentp NULL\n");
532 gtk_tree_path_free(parentp);
533 parentp = NULL;
534 }
535 }
536 } else {
537 parent = snwiz->snw->lastclickednode;
538 DEBUG_MSG("clicked node was a branch\n");
539 }
540 } else { /* parent must be the root element <snippets> */
541 parent = xmlDocGetRootElement(snippets_v.doc);
542 }
543 DEBUG_MSG("snippets_test_pageBranch, xml-adding %s to parent %s\n",name,(gchar *)parent->name);
544 child = xmlNewChild(parent,NULL,(const xmlChar *)"branch",NULL);
545 xmlSetProp(child, (const xmlChar *)"title", (const xmlChar *)name);
546 /* add this branch to the treestore */
547 DEBUG_MSG("snippets_test_pageBranch, store-adding %s to parentp=%p\n",name,parentp);
548 if (parentp) {
549 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(snippets_v.store),&piter,parentp)) {
550 gtk_tree_store_append(snippets_v.store, &citer, &piter);
551 } else {
552 g_print("hmm weird error!?!\n");
553 }
554 } else {
555 gtk_tree_store_append(snippets_v.store, &citer, NULL);
556 }
557 gtk_tree_store_set(snippets_v.store, &citer, PIXMAP_COLUMN,NULL,TITLE_COLUMN, name,NODE_COLUMN, child,-1);
558 }
559
560 DEBUG_MSG("add branch with title %s\n",name);
561 g_free(name);
562 g_idle_add(snippets_store_lcb, NULL);
563 return page_finished;
564 }
565
566 typedef struct {
567 GtkWidget *name;
568 GtkWidget *description;
569 GtkWidget *vbox;
570 } TpageName;
571
snippets_build_pageName(Tsnipwiz * snwiz,GtkWidget * dialog_action)572 static gpointer snippets_build_pageName(Tsnipwiz *snwiz, GtkWidget *dialog_action) {
573 GtkWidget *label, *scrolwin;
574 gchar *namestr=NULL, *descstr=NULL;
575 TpageName *p = g_new(TpageName,1);
576
577 if (snwiz->node) { /* we're editing a node! */
578 namestr = (gchar *)xmlGetProp(snwiz->node, (const xmlChar *)"title");
579 descstr = (gchar *)xmlGetProp(snwiz->node, (const xmlChar *)"tooltip");
580 }
581
582 p->vbox = gtk_vbox_new(FALSE,12);
583 gtk_container_add(GTK_CONTAINER(dialog_action),p->vbox);
584 label = gtk_label_new(_("Name of the new item:"));
585 gtk_box_pack_start(GTK_BOX(p->vbox),label,TRUE,FALSE,12);
586 p->name = gtk_entry_new();
587 if (namestr) gtk_entry_set_text(GTK_ENTRY(p->name),namestr);
588 gtk_box_pack_start(GTK_BOX(p->vbox),p->name,TRUE,FALSE,12);
589 label = gtk_label_new(_("Description:"));
590 gtk_box_pack_start(GTK_BOX(p->vbox),label,TRUE,FALSE,12);
591 scrolwin = textview_buffer_in_scrolwin(&p->description, -1, -1, descstr, GTK_WRAP_NONE);
592 gtk_box_pack_start(GTK_BOX(p->vbox),scrolwin,TRUE,TRUE,12);
593
594 gtk_widget_show_all(p->vbox);
595 g_free(namestr);
596 g_free(descstr);
597 return p;
598 }
599
snippets_delete_pageName(Tsnipwiz * snwiz,gpointer data)600 static void snippets_delete_pageName(Tsnipwiz *snwiz, gpointer data) {
601 TpageName *p = (TpageName *)data;
602 gtk_widget_destroy(p->vbox);
603 g_free(p);
604 }
605
snippets_test_pageName(Tsnipwiz * snwiz,gpointer data)606 static gint snippets_test_pageName(Tsnipwiz *snwiz, gpointer data) {
607 TpageName *p = (TpageName *)data;
608 gchar *name, *desc;
609
610 name = gtk_editable_get_chars(GTK_EDITABLE(p->name),0,-1);
611 desc = textbuffer_get_all_chars(gtk_text_view_get_buffer(GTK_TEXT_VIEW(p->description)));
612 if (strlen(name)) {
613 snwiz->name = name;
614 snwiz->description = desc;
615 if (snwiz->choice == 1) {
616 return page_insert;
617 } else {
618 return page_snr;
619 }
620 } else {
621 /* warn */
622
623 g_free(name);
624 g_free(desc);
625 return page_name;
626 }
627 }
628
629 typedef struct {
630 GtkWidget *radio[3];
631 GtkWidget *vbox;
632 } TpageType;
633
snippets_build_pageType(Tsnipwiz * snwiz,GtkWidget * dialog_action)634 static gpointer snippets_build_pageType(Tsnipwiz *snwiz, GtkWidget *dialog_action) {
635 GtkWidget *label;
636 TpageType *p0 = g_new(TpageType,1);
637 p0->vbox = gtk_vbox_new(FALSE,12);
638 gtk_container_add(GTK_CONTAINER(dialog_action),p0->vbox);
639 label = gtk_label_new(_("Select what you want to add"));
640 gtk_box_pack_start(GTK_BOX(p0->vbox),label,TRUE,TRUE,12);
641 p0->radio[0] = gtk_radio_button_new_with_label(NULL, _("Branch"));
642 gtk_box_pack_start(GTK_BOX(p0->vbox),p0->radio[0],TRUE,TRUE,12);
643 p0->radio[1] = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(p0->radio[0]),_("Insert string"));
644 gtk_box_pack_start(GTK_BOX(p0->vbox),p0->radio[1],TRUE,TRUE,12);
645 p0->radio[2] = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(p0->radio[0]),_("Search and replace pattern"));
646 gtk_box_pack_start(GTK_BOX(p0->vbox),p0->radio[2],TRUE,TRUE,12);
647 gtk_widget_show_all(p0->vbox);
648 DEBUG_MSG("snippets_build_pageType, created pageType at %p\n",p0);
649 return p0;
650 }
651
snippets_delete_pageType(Tsnipwiz * snwiz,gpointer data)652 static void snippets_delete_pageType(Tsnipwiz *snwiz, gpointer data) {
653 TpageType *p0 = (TpageType *)data;
654 DEBUG_MSG("snippets_delete_pageType, destroy pageType at %p\n",p0);
655 gtk_widget_destroy(p0->vbox);
656 g_free(p0);
657 }
658
snippets_test_pageType(Tsnipwiz * snwiz,gpointer data)659 static gint snippets_test_pageType(Tsnipwiz *snwiz, gpointer data) {
660 TpageType *p0 = (TpageType *)data;
661 int i;
662 DEBUG_MSG("snippets_delete_pageType, test pageType at %p\n",p0);
663 for (i=0;i<3;i++) {
664 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(p0->radio[i]))) {
665 snwiz->choice = i;
666 if (i==0) return page_branch;
667 else return page_name;
668 }
669 }
670 return page_type;
671 }
672
snipwiz_dialog_response_lcb(GtkDialog * dialog,gint response,Tsnipwiz * snwiz)673 static void snipwiz_dialog_response_lcb(GtkDialog *dialog, gint response, Tsnipwiz *snwiz) {
674 Tpagenum newpagenum=page_type;
675 DEBUG_MSG("snipwiz_dialog_response_lcb, response=%d\n",response);
676 if (response == GTK_RESPONSE_REJECT) {
677 gtk_widget_destroy(snwiz->dialog);
678 g_free(snwiz);
679 return;
680 }
681 switch (snwiz->pagenum) { /* test the current results */
682 case page_type:
683 newpagenum = snippets_test_pageType(snwiz,snwiz->pagestruct);
684 if (newpagenum != page_type) {
685 snippets_delete_pageType(snwiz,snwiz->pagestruct);
686 }
687 break;
688 case page_name:
689 newpagenum = snippets_test_pageName(snwiz,snwiz->pagestruct);
690 if (newpagenum != page_name) {
691 snippets_delete_pageName(snwiz,snwiz->pagestruct);
692 }
693 break;
694 case page_branch:
695 newpagenum = snippets_test_pageBranch(snwiz,snwiz->pagestruct);
696 if (newpagenum != page_branch) {
697 snippets_delete_pageBranch(snwiz,snwiz->pagestruct);
698 }
699 break;
700 case page_insert:
701 newpagenum = snippets_test_pageInsert(snwiz,snwiz->pagestruct);
702 if (newpagenum != page_insert) {
703 snippets_delete_pageInsert(snwiz,snwiz->pagestruct);
704 }
705 break;
706 case page_snr:
707 newpagenum = snippets_test_pageSnr(snwiz,snwiz->pagestruct);
708 if (newpagenum != page_snr) {
709 snippets_delete_pageSnr(snwiz,snwiz->pagestruct);
710 }
711 break;
712 case page_finished: /* avoid compiler warning */
713 break;
714 }
715 if (snwiz->pagenum != newpagenum) {
716 GtkWidget *vbox = gtk_dialog_get_content_area(GTK_DIALOG(snwiz->dialog));
717 switch (newpagenum) { /* build a new page */
718 case page_type:
719 snwiz->pagestruct = snippets_build_pageType(snwiz, vbox);
720 break;
721 case page_name:
722 snwiz->pagestruct = snippets_build_pageName(snwiz, vbox);
723 break;
724 case page_branch:
725 snwiz->pagestruct = snippets_build_pageBranch(snwiz, vbox);
726 break;
727 case page_insert:
728 snwiz->pagestruct = snippets_build_pageInsert(snwiz, vbox);
729 break;
730 case page_snr:
731 snwiz->pagestruct = snippets_build_pageSnr(snwiz, vbox);
732 break;
733 case page_finished:
734 gtk_widget_destroy(snwiz->dialog);
735 if (snwiz->name) g_free(snwiz->name);
736 if (snwiz->description) g_free(snwiz->description);
737 g_free(snwiz);
738 g_idle_add(snippets_store_lcb, NULL);
739 return;
740 break;
741 }
742 snwiz->pagenum = newpagenum;
743 }
744 }
745
746
snippets_new_item_dialog(Tsnippetswin * snw,xmlNodePtr node)747 void snippets_new_item_dialog(Tsnippetswin *snw, xmlNodePtr node) {
748 Tsnipwiz *snwiz;
749 GtkWidget *vbox;
750
751 snwiz = g_new0(Tsnipwiz,1);
752 snwiz->snw = snw;
753 snwiz->node = node;
754 snwiz->dialog = gtk_dialog_new_with_buttons(node? _("Edit snippet") :_("New snippet"),GTK_WINDOW(snw->bfwin->main_window),
755 GTK_DIALOG_DESTROY_WITH_PARENT,
756 GTK_STOCK_CANCEL,GTK_RESPONSE_REJECT,
757 GTK_STOCK_GO_FORWARD,1,
758 NULL);
759 gtk_window_set_default_size(GTK_WINDOW(snwiz->dialog),500,400);
760 g_signal_connect(G_OBJECT(snwiz->dialog), "response", G_CALLBACK(snipwiz_dialog_response_lcb), snwiz);
761 vbox = gtk_dialog_get_content_area(GTK_DIALOG(snwiz->dialog));
762 if (node) {
763 if (xmlStrEqual(snw->lastclickednode->name, (const xmlChar *)"leaf")) {
764 xmlChar *type = xmlGetProp(node, (const xmlChar *)"type");
765 if (xmlStrEqual(type, (const xmlChar *)"insert")) {
766 snwiz->choice = 1;
767 } else if (xmlStrEqual(type, (const xmlChar *)"snr")) {
768 snwiz->choice = 2;
769 }
770 snwiz->pagestruct = snippets_build_pageName(snwiz, vbox);
771 snwiz->pagenum = page_name;
772 } else {
773 snwiz->pagestruct = snippets_build_pageBranch(snwiz, vbox);
774 snwiz->pagenum = page_branch;
775 }
776 } else {
777 if (!snw->lastclickednode) {
778 snwiz->pagestruct = snippets_build_pageBranch(snwiz, vbox);
779 snwiz->pagenum = page_branch;
780 } else {
781 snwiz->pagestruct = snippets_build_pageType(snwiz, vbox);
782 snwiz->pagenum = page_type;
783 }
784 }
785 gtk_widget_show_all(snwiz->dialog);
786 }
787