1
/* Bluefish HTML Editor - bookmarks
3
* Copyright (C) 2003 Oskar Swida
4
* modifications (C) 2004 Olivier Sessink
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 2 of the License, or
9
* (at your option) any later version.
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.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
#include <sys/types.h>
33
#include "stringlist.h"
37
bookmarks will be loaded and saved to an arraylist (see stringlist.c). This
38
is a double linked list (GList *) with pointers to string arrays (gchar **).
40
To have the GUI work with them, we convert those arrays (gchar **) into a
41
Tbmark struct. This struct will ahve a pointer to the array (gchar **) so
42
on change it can directly change the array as well, without any need to
43
look it up in the list.
45
For the GUI, we store everything in a Gtktreestore. The treestore will have a
46
pointer to a string with the name, and it will also have a pointer to the
47
Tbmark. When the user clicks in the Gtktreeview widget, we can get
48
immediately a pointer to the Tbmark, and that has the Gtktextmark, so that
49
is very easy, and very fast!
51
But now we have one problem: all normal windows do share the same bookmarks list.
52
So it is probably the most logical to have them store the same Gtktreestore as
53
well. The best way is to have the project functions create/destroy the
54
gtktreestore when they convert a window (Tbfwin) into a project window.
57
#define BMARK_SHOW_NUM_TEXT_CHARS 20
60
NAME_COLUMN, /* bookmark name */
61
PTR_COLUMN, /* bookmark pointer */
66
BMARK_ADD_PERM_DIALOG,
67
BMARK_RENAME_TEMP_DIALOG,
68
BMARK_RENAME_PERM_DIALOG
76
GtkTreeIter iter; /* for tree view */
80
gint len; /* file length for integrity check - perhaps some hash code is needed */
82
gchar **strarr; /* this is a pointer to the location where this bookmark is stored in the sessionlist,
83
so we can immediately change it _in_ the list */
85
#define BMARK(var) ((Tbmark *)(var))
88
Tdocument *bevent_doc; /* last button event document */
89
gint bevent_charoffset; /* last button event location */
91
#define BMARKDATA(var) ((Tbmarkdata *)(var))
93
#define BM_FMODE_FULL 0
94
#define BM_FMODE_HOME 1
95
#define BM_FMODE_FILE 2
97
static gchar *bmark_display_text(gchar *name, gchar *text) {
98
if (name && strlen(name) > 0) {
99
return g_strconcat(name, " - ", text,NULL);
101
return g_strdup(text);
104
/* Free bookmark structure */
105
static void bmark_free(gpointer ptr)
111
if (m->doc && m->mark) {
112
DEBUG_MSG("bmark_free, deleting mark %p\n",m->mark);
113
gtk_text_buffer_delete_mark(m->doc->buffer, m->mark);
118
DEBUG_MSG("bmark_free, NOT GOOD, strarr should be NULL here...\n");
124
g_free(m->description);
128
static void bmark_update_offset_from_textmark(Tbmark *b) {
129
if (b->doc && b->mark) {
131
gtk_text_buffer_get_iter_at_mark(b->doc->buffer, &it, b->mark);
132
b->offset = gtk_text_iter_get_offset(&it);
137
* this function should use a smart sorting algorithm to find
138
* the GtkTreeIter of the bookmark *before* the place where this
139
* bookmark should be added, but the same function can be used to
140
* find the bookmarks we have to check to detect double bookmarks
143
* returns the bookmark closest before 'offset', or the bookmark exactly at 'offset'
145
* returns NULL if we have to append this as first child to the parent
148
static Tbmark *bmark_find_bookmark_before_offset(Tbfwin *bfwin, guint offset, GtkTreeIter *parent) {
149
gint jumpsize, num_children, child;
152
num_children = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(bfwin->bookmarkstore), parent);
153
if (num_children == 0) {
157
if (num_children == 1) {
160
gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(bfwin->bookmarkstore), &iter, parent, 0);
161
gtk_tree_model_get(GTK_TREE_MODEL(bfwin->bookmarkstore),&iter,PTR_COLUMN,&b, -1);
163
bmark_update_offset_from_textmark(b);
164
DEBUG_MSG("bmark_find_bookmark_before_offset, num_children=%d\n",num_children);
165
compare = (offset - b->offset);
173
jumpsize = (num_children+2)/2;
174
child = num_children + 1 - jumpsize;
175
DEBUG_MSG("bmark_find_bookmark_before_offset, num_children=%d,jumpsize=%d,child=%d\n",num_children,jumpsize,child);
176
while (jumpsize > 0) {
180
if (child > num_children) child = num_children;
181
if (child < 1) child = 1;
182
/* we request child-1, NOT child*/
183
gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(bfwin->bookmarkstore), &iter, parent, child-1);
184
gtk_tree_model_get(GTK_TREE_MODEL(bfwin->bookmarkstore),&iter,PTR_COLUMN,&b, -1);
186
bmark_update_offset_from_textmark(b);
187
compare = (offset - b->offset);
188
DEBUG_MSG("in_loop: jumpsize=%2d, child=%2d, child offset=%3d, compare=%3d\n",jumpsize,child,b->offset,compare);
191
} else if (compare < 0) {
192
jumpsize = (jumpsize > 3) ? (jumpsize+1)/2 : jumpsize-1;
195
/* we request child-1, NOT child*/
196
if (child >= 1 && gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(bfwin->bookmarkstore), &iter, parent, child-1)) {
197
gtk_tree_model_get(GTK_TREE_MODEL(bfwin->bookmarkstore),&iter,PTR_COLUMN,&b, -1);
198
bmark_update_offset_from_textmark(b);
199
DEBUG_MSG("in_loop: returning bookmark (offset %d) for previous child %d\n",b->offset, child);
202
DEBUG_MSG("in_loop: no previous child, return NULL\n");
206
child = child - jumpsize;
207
} else { /* compare > 0 */
208
jumpsize = (jumpsize > 3) ? (jumpsize+1)/2 : jumpsize-1;
210
DEBUG_MSG("in_loop: return bookmark (offset %d) from child %d\n",b->offset, child);
213
child = child + jumpsize;
216
DEBUG_MSG("bmark_find_bookmark_before_offset, end-of-function, return NULL\n");
220
/* this function re-uses the b->strarr if possible, otherwise it will create a new one and
221
append it to the list */
222
static void bmark_store(Tbfwin * bfwin, Tbmark * b) {
225
DEBUG_MSG("bmark_store, called for temp bookmark %p ?!?! weird!!!! returning\n", b);
229
/* if there is a strarr already, we only update the fields, else we append a new one */
230
if (b->strarr == NULL) {
231
DEBUG_MSG("bmark_store, creating new strarr for bookmark %p\n",b);
232
strarr = g_malloc0(sizeof(gchar *) * 7);
233
DEBUG_MSG("name=%s, description=%s, filepath=%s, text=%s\n", b->name, b->description, b->filepath, b->text);
234
strarr[2] = g_strdup(b->filepath);
235
strarr[4] = g_strdup(b->text);
237
DEBUG_MSG("bmark_store, bookmark %p has strarr at %p\n",b,b->strarr);
239
/* free the ones we are going to update */
245
strarr[0] = g_strdup(b->name);
246
strarr[1] = g_strdup(b->description);
247
#ifdef HAVE_GNOME_VFS
249
b->len = b->doc->fileinfo->size;
252
b->len = b->doc->statbuf.st_size;
254
strarr[3] = g_strdup_printf("%d", b->offset);
255
DEBUG_MSG("bmark_store, offset string=%s, offset int=%d\n",strarr[3],b->offset);
256
strarr[5] = g_strdup_printf("%d", b->len);
257
DEBUG_MSG("bmark_store, arracount=%d\n",count_array(strarr));
258
if (b->strarr == NULL) {
259
bfwin->session->bmarks = g_list_append(bfwin->session->bmarks, strarr);
260
DEBUG_MSG("added new (previously unstored) bookmark to session list, list length=%d\n",
261
g_list_length(bfwin->session->bmarks));
266
/* when a users want to save the project, it's good to have updated bookmarks
267
so this function will update all arrays (strarr**)
269
void bmark_store_all(Tbfwin *bfwin) {
270
/* we loop over all filename iters, and only for the ones that are opened
271
we loop over the children (the ones that are not open cannot be changed) */
275
cont = gtk_tree_model_iter_children(GTK_TREE_MODEL(BFWIN(bfwin)->bookmarkstore), &fileit,NULL);
277
Tdocument *doc = NULL;
278
gtk_tree_model_get(GTK_TREE_MODEL(BFWIN(bfwin)->bookmarkstore), &fileit, PTR_COLUMN,&doc, -1);
280
/* the document is open, so the offsets could be changed, store all permanent */
282
gboolean cont2 = gtk_tree_model_iter_children(GTK_TREE_MODEL(BFWIN(bfwin)->bookmarkstore), &bmit,&fileit);
283
DEBUG_MSG("bmark_store_all, storing bookmarks for %s\n",doc->filename);
286
gtk_tree_model_get(GTK_TREE_MODEL(BFWIN(bfwin)->bookmarkstore), &bmit, PTR_COLUMN,&bmark, -1);
287
if (!bmark->is_temp) {
288
bmark_update_offset_from_textmark(bmark);
289
bmark_store(bfwin, bmark);
291
cont2 = gtk_tree_model_iter_next(GTK_TREE_MODEL(BFWIN(bfwin)->bookmarkstore), &bmit);
294
DEBUG_MSG("doc not set, so not open...\n");
296
cont = gtk_tree_model_iter_next(GTK_TREE_MODEL(BFWIN(bfwin)->bookmarkstore), &fileit);
300
/* removes the bookmark from the session, removed the b->strarr pointer and frees it */
301
static void bmark_unstore(Tbfwin * bfwin, Tbmark * b)
303
if (bfwin->session->bmarks == NULL || b->strarr == NULL)
305
DEBUG_MSG("bmark_remove, removing bookmark %p from sessionlist\n",b);
306
bfwin->session->bmarks = g_list_remove(bfwin->session->bmarks, b->strarr);
307
g_strfreev(b->strarr);
311
/* get value from pointer column */
312
static gpointer get_current_bmark(Tbfwin * bfwin)
316
GtkTreeViewColumn *col;
317
gtk_tree_view_get_cursor(bfwin->bmark, &path, &col);
319
gpointer retval = NULL;
321
gtk_tree_model_get_iter(gtk_tree_view_get_model(bfwin->bmark), &iter, path);
322
gtk_tree_model_get(gtk_tree_view_get_model(bfwin->bmark),&iter,1, &retval, -1);
323
gtk_tree_path_free(path);
324
DEBUG_MSG("get_current_bmark, returning %p\n",retval);
331
void bmark_name_entry_changed(GtkEntry * entry, GtkDialog * dialog)
335
string = gtk_entry_get_text(GTK_ENTRY(entry));
336
if (strlen(string) <= 0)
337
gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), GTK_RESPONSE_OK, FALSE);
339
gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), GTK_RESPONSE_OK, TRUE);
342
void bmark_add_rename_dialog(Tbfwin * bfwin, gchar * dialogtitle)
344
GtkWidget *dlg, *name, *desc, *button, *table, *istemp;
348
GtkTextIter it, sit, eit;*/
349
Tbmark *m = get_current_bmark(bfwin);
353
gtk_dialog_new_with_buttons(dialogtitle, GTK_WINDOW(bfwin->main_window), GTK_DIALOG_MODAL,
354
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
355
button = gtk_button_new_from_stock(GTK_STOCK_OK);
356
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
357
gtk_dialog_add_action_widget(GTK_DIALOG(dlg), button, GTK_RESPONSE_OK);
358
/* gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE);*/
359
table = gtk_table_new(2, 3, FALSE);
360
gtk_table_set_col_spacings(GTK_TABLE(table), 12);
361
gtk_table_set_row_spacings(GTK_TABLE(table), 6);
362
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), table, FALSE, FALSE, 12);
364
name = entry_with_text(m->name, 200);
365
gtk_entry_set_activates_default(GTK_ENTRY(name), TRUE);
366
bf_mnemonic_label_tad_with_alignment(_("_Name:"), name, 0, 0.5, table, 0, 1, 0, 1);
367
gtk_table_attach_defaults(GTK_TABLE(table), name, 1, 2, 0, 1);
368
/* g_signal_connect(G_OBJECT(name), "changed", G_CALLBACK(bmark_name_entry_changed), dlg);*/
369
desc = entry_with_text(m->description, 200);
370
gtk_entry_set_activates_default(GTK_ENTRY(desc), TRUE);
371
bf_mnemonic_label_tad_with_alignment(_("_Description:"), desc, 0, 0.5, table, 0, 1, 1, 2);
372
gtk_table_attach_defaults(GTK_TABLE(table), desc, 1, 2, 1, 2);
373
istemp = checkbut_with_value(_("Temporary"), m->is_temp);
374
gtk_table_attach_defaults(GTK_TABLE(table), istemp, 0, 2, 2, 3);
376
gtk_window_set_default(GTK_WINDOW(dlg), button);
378
gtk_widget_show_all(dlg);
379
result = gtk_dialog_run(GTK_DIALOG(dlg));
381
if (result == GTK_RESPONSE_OK) {
383
/* check if name exists */
384
/* if (bmark_name_exists
385
(DOCUMENT(bfwin->current_document), gtk_entry_get_text(GTK_ENTRY(name)))) {
387
g_strdup_printf(_("You already have a bookmark named %s!"),
388
gtk_entry_get_text(GTK_ENTRY(name)));
389
if (dialogtype == BMARK_ADD_PERM_DIALOG) {
390
info_dialog(bfwin->main_window, dialogtitle, pstr);
392
info_dialog(bfwin->main_window, dialogtitle, pstr);
395
gtk_widget_destroy(dlg);
396
bmark_add_rename_dialog(bfwin, dialogtitle, dialogtype);
399
/* if (dialogtype == BMARK_ADD_PERM_DIALOG) {
400
m = g_new0(Tbmark, 1);
401
m->doc = DOCUMENT(bfwin->current_document);
404
im = gtk_text_buffer_get_insert(m->doc->buffer);
405
gtk_text_buffer_get_iter_at_mark(m->doc->buffer, &it, im);
407
gtk_text_buffer_create_mark(m->doc->buffer,
408
g_strdup(gtk_entry_get_text(GTK_ENTRY(name))), &it,
410
m->filepath = g_strdup(m->doc->filename);
412
m->name = g_strdup(gtk_entry_get_text(GTK_ENTRY(name)));
413
m->description = g_strdup(gtk_entry_get_text(GTK_ENTRY(desc)));
415
gtk_text_iter_forward_to_line_end(&eit);
416
gtk_text_iter_forward_chars(&sit, 10);
417
if (!gtk_text_iter_in_range(&sit, &it, &eit))
419
m->text = g_strdup(gtk_text_iter_get_slice(&it, &sit));
421
bmark_get_iter_at_tree_position(bfwin, m);
422
gtk_tree_store_set(bfwin->bookmarkstore, &m->iter, NAME_COLUMN,
423
g_strdup_printf("[%s] --> %s", gtk_entry_get_text(GTK_ENTRY(name)),
424
m->text), PTR_COLUMN, m, -1);
425
gtk_tree_view_expand_all(bfwin->bmark);
426
gtk_widget_grab_focus(bfwin->current_document->view);
427
bmark_store(bfwin, m);
430
m->name = g_strdup(gtk_entry_get_text(GTK_ENTRY(name)));
431
g_free(m->description);
432
m->description = g_strdup(gtk_entry_get_text(GTK_ENTRY(desc)));
433
m->is_temp = GTK_TOGGLE_BUTTON(istemp)->active;
434
if (m->name && strlen(m->name) > 0) {
435
tmpstr = g_strconcat(m->name, " - ", m->text,NULL);
437
tmpstr = g_strdup(m->text);
439
gtk_tree_store_set(bfwin->bookmarkstore, &m->iter, NAME_COLUMN,
444
/* hmm previously this was not a temporary bookmark */
445
bmark_unstore(bfwin, m);
448
bmark_store(bfwin, m);
452
gtk_widget_destroy(dlg);
455
static void bmark_popup_menu_goto_lcb(GtkWidget * widget, gpointer user_data)
462
b = get_current_bmark(BFWIN(user_data));
465
if (b->filepath && !b->doc) {
466
/* check if that document _is_ open */
468
GList *doclist = return_allwindows_documentlist();
469
tmpdoc = documentlist_return_document_from_filename(doclist, b->filepath);
470
g_list_free(doclist);
471
if (tmpdoc == NULL) {
472
if (!g_file_test(b->filepath, G_FILE_TEST_EXISTS)) {
473
gchar *string = g_strdup_printf(_("Could not find the file \"%s\"."), b->filepath);
474
error_dialog(BFWIN(user_data)->main_window, string,
475
_("This bookmark is set in a file that no longer exists."));
479
tmpdoc = doc_new_with_file(BFWIN(user_data), b->filepath, FALSE, TRUE);
481
/* now I have to check all bookmarks */
482
bmark_set_for_doc(tmpdoc);
486
GdkRectangle visirect;
487
GtkTextIter visi_so, visi_eo;
488
gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(b->doc->view),&visirect);
489
gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(b->doc->view), &visi_so, visirect.x, visirect.y);
490
gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(b->doc->view), &visi_eo, visirect.x + visirect.width, visirect.y + visirect.height);
492
gtk_text_buffer_get_iter_at_mark(b->doc->buffer, &it, b->mark);
493
gtk_text_buffer_place_cursor(b->doc->buffer, &it);
495
if (!gtk_text_iter_in_range(&it,&visi_so,&visi_eo)) {
496
DEBUG_MSG("bmark_popup_menu_goto_lcb, cursor NOT visible!\n");
497
/* gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(b->doc->view), b->mark); */
498
gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(b->doc->view),b->mark,0.0,
501
if (b->doc != BFWIN(user_data)->current_document)
502
switch_to_document_by_pointer(BFWIN(user_data), b->doc);
503
gtk_widget_grab_focus(b->doc->view);
507
* removes the bookmark from the treestore, and if it is the last remaining bookmark
508
* for the document, it will remove the parent iter (the filename) from the treestore as well
510
static void bmark_check_remove(Tbfwin *bfwin,Tbmark *b) {
512
if (gtk_tree_model_iter_parent(GTK_TREE_MODEL(bfwin->bookmarkstore),&parent,&b->iter)) {
513
gint numchild = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(bfwin->bookmarkstore), &parent);
514
DEBUG_MSG("bmark_check_remove, the parent of this bookmark has %d children\n", numchild);
515
gtk_tree_store_remove(bfwin->bookmarkstore, &(b->iter));
518
DEBUG_MSG("bmark_check_remove, we removed the last child, now remove the parent\n");
519
gtk_tree_store_remove(bfwin->bookmarkstore,&parent);
520
/* if the document is open, it should be removed from the hastable as well */
521
ptr = g_hash_table_lookup(bfwin->bmark_files,b->filepath);
523
DEBUG_MSG("bmark_check_remove, removing iter from hashtable\n");
524
g_hash_table_remove(bfwin->bmark_files,b->filepath);
526
if (b->doc) b->doc->bmark_parent = NULL;
531
gtk_tree_model_get(GTK_TREE_MODEL(bfwin->bookmarkstore), &b->iter, NAME_COLUMN,&name, -1);
532
g_print("bmark_check_remove, very weird, bookmark %s for %s does not have a parent ?????\n",name,b->filepath);
537
/* according to the gtk documentation this function is slow and should be used
538
only for testing purposes
539
if ( gtk_tree_store_iter_is_valid(bfwin->bookmarkstore, &(b->iter)) )*/
540
/* DEBUG_MSG("bmark_check_remove, removing bookmark %p from treestore\n",b);
541
gtk_tree_store_remove(bfwin->bookmarkstore, &(b->iter));
542
if (bfwin->bmark_files) {
543
ptr = g_hash_table_lookup(bfwin->bmark_files,b->filepath);
545
DEBUG_MSG("bmark_check_remove, %s has an entry in the hashtable\n",b->filepath);
546
if (!gtk_tree_model_iter_has_child(GTK_TREE_MODEL(bfwin->bookmarkstore), (GtkTreeIter*)ptr)) {
548
DEBUG_MSG("bmark_check_remove, the entry in the hashtable does NOT have a child, re=%d\n", re);
550
DEBUG_MSG("bmark_check_remove, the entry in the hashtable does have a child\n");
555
/ *if (gtk_tree_store_iter_is_valid(bfwin->bookmarkstore,(GtkTreeIter*)ptr))* /
556
DEBUG_MSG("bmark_check_remove, removing the entry from the treestore\n");
557
gtk_tree_store_remove(bfwin->bookmarkstore,(GtkTreeIter*)ptr);
558
DEBUG_MSG("bmark_check_remove, removing the entry from the hashtable\n");
559
g_hash_table_remove(bfwin->bmark_files,b->filepath);
561
if (b->doc) b->doc->bmark_parent = NULL;
563
DEBUG_MSG("bmark_check_remove, finished\n");
566
static void bmark_del_children_backend(Tbfwin *bfwin, GtkTreeIter *parent) {
568
while (gtk_tree_model_iter_children(GTK_TREE_MODEL(bfwin->bookmarkstore), &tmpiter, parent)) {
570
gtk_tree_model_get(GTK_TREE_MODEL(bfwin->bookmarkstore), &tmpiter, PTR_COLUMN,&b,-1);
572
DEBUG_MSG("bmark_del_children_backend, found b=%p\n",b);
573
bmark_check_remove(bfwin,b);
575
bmark_unstore(bfwin, b);
578
DEBUG_MSG("bmark_del_children_backend, iter without bookmark ??? LOOP WARNING!\n");
584
static void bmark_popup_menu_deldoc_lcb(GtkWidget * widget, Tbfwin *bfwin) {
587
GtkTreeViewColumn *col;
588
gtk_tree_view_get_cursor(bfwin->bmark, &path, &col);
592
gchar *btns[] = { GTK_STOCK_NO, GTK_STOCK_YES, NULL };
595
depth = gtk_tree_path_get_depth(path);
597
/* go up to parent */
598
gtk_tree_path_up(path);
599
} else if (depth != 1) {
600
g_print("a bug in function bmark_popup_menu_deldoc_lcb()\n");
606
gtk_tree_model_get_iter(gtk_tree_view_get_model(bfwin->bmark), &iter, path);
607
gtk_tree_path_free(path);
608
gtk_tree_model_get(GTK_TREE_MODEL(bfwin->bookmarkstore), &iter, NAME_COLUMN,&name, -1);
610
pstr = g_strdup_printf(_("Do you really want to delete all bookmarks for %s?"), name);
611
ret = multi_query_dialog(bfwin->main_window, _("Delete bookmarks?"), pstr,
616
bmark_del_children_backend(bfwin, &iter);
619
gtk_widget_grab_focus(bfwin->current_document->view);
622
static void bmark_popup_menu_del_lcb(GtkWidget * widget, gpointer user_data)
627
gchar *btns[] = { GTK_STOCK_NO, GTK_STOCK_YES, NULL };
631
b = get_current_bmark(BFWIN(user_data));
634
/* check if it is temp mark */
636
/* gtk_tree_store_remove(BFWIN(user_data)->bookmarkstore, &(b->iter)); */
637
bmark_check_remove(BFWIN(user_data),b); /* check if we should remove a filename too */
638
/* bmark_unstore(BFWIN(user_data), b); */
641
pstr = g_strdup_printf(_("Do you really want to delete %s?"), b->name);
643
multi_query_dialog(BFWIN(user_data)->main_window, _("Delete permanent bookmark."), pstr,
648
bmark_check_remove(BFWIN(user_data),b); /* check if we should remove a filename too */
649
bmark_unstore(BFWIN(user_data), b);
653
gtk_widget_grab_focus(BFWIN(user_data)->current_document->view);
656
static void bmark_popup_menu_rename_lcb(GtkWidget * widget, Tbfwin * bfwin)
658
Tbmark *m = get_current_bmark(bfwin);
660
bmark_add_rename_dialog(bfwin, _("Edit bookmark"));
663
static void bmark_popup_menu_delall_lcb(GtkWidget * widget, Tbfwin * bfwin)
665
bmark_del_all(bfwin,TRUE);
669
static GtkWidget *bmark_popup_menu(Tbfwin * bfwin, gboolean show_bmark_specific, gboolean show_file_specific) {
670
GtkWidget *menu, *menu_item;
672
menu = gtk_menu_new();
673
if (show_bmark_specific) {
674
menu_item = gtk_menu_item_new_with_label(_("Goto bookmark"));
675
g_signal_connect(GTK_OBJECT(menu_item), "activate", G_CALLBACK(bmark_popup_menu_goto_lcb),
677
gtk_menu_append(GTK_MENU(menu), menu_item);
679
menu_item = gtk_separator_menu_item_new();
680
gtk_menu_append(GTK_MENU(menu), menu_item);
682
menu_item = gtk_menu_item_new_with_label(_("Edit"));
683
g_signal_connect(GTK_OBJECT(menu_item), "activate", G_CALLBACK(bmark_popup_menu_rename_lcb),
685
gtk_menu_append(GTK_MENU(menu), menu_item);
686
menu_item = gtk_menu_item_new_with_label(_("Delete"));
687
g_signal_connect(GTK_OBJECT(menu_item), "activate", G_CALLBACK(bmark_popup_menu_del_lcb),
689
gtk_menu_append(GTK_MENU(menu), menu_item);
691
if (show_file_specific) {
692
menu_item = gtk_menu_item_new_with_label(_("Delete all in document"));
693
g_signal_connect(GTK_OBJECT(menu_item), "activate", G_CALLBACK(bmark_popup_menu_deldoc_lcb),
695
gtk_menu_append(GTK_MENU(menu), menu_item);
697
menu_item = gtk_menu_item_new_with_label(_("Delete all"));
698
g_signal_connect(GTK_OBJECT(menu_item), "activate", G_CALLBACK(bmark_popup_menu_delall_lcb),
700
gtk_menu_append(GTK_MENU(menu), menu_item);
702
gtk_widget_show_all(menu);
703
g_signal_connect_after(G_OBJECT(menu), "destroy", G_CALLBACK(destroy_disposable_menu_cb), menu);
709
/* right mouse click */
710
static gboolean bmark_event_mouseclick(GtkWidget * widget, GdkEventButton * event, Tbfwin * bfwin) {
712
gboolean show_bmark_specific = FALSE, show_file_specific = FALSE;
713
if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(bfwin->bmark), event->x, event->y, &path, NULL, NULL, NULL)) {
715
gint depth = gtk_tree_path_get_depth(path);
716
gtk_tree_path_free(path);
718
show_bmark_specific = TRUE;
719
show_file_specific = TRUE;
720
if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { /* double click */
721
bmark_popup_menu_goto_lcb(NULL, bfwin);
724
} else if (depth == 1) {
725
show_file_specific = TRUE;
729
if (event->button == 3 && event->type == GDK_BUTTON_PRESS) { /* right mouse click */
730
gtk_menu_popup(GTK_MENU(bmark_popup_menu(bfwin, show_bmark_specific, show_file_specific)), NULL, NULL, NULL, NULL,
731
event->button, event->time);
736
/* Initialize bookmarks gui for window */
738
GtkWidget *bmark_gui(Tbfwin * bfwin)
740
GtkWidget *vbox, *scroll;
741
GtkCellRenderer *cell;
742
GtkTreeViewColumn *column;
743
DEBUG_MSG("bmark_gui, building gui for bfwin=%p\n",bfwin);
744
/* Tree Store is in bfwin->bookmarkstore
745
Tree View is in bfwin->bmark
747
vbox = gtk_vbox_new(FALSE, 1);
748
bfwin->bmark = gtk_tree_view_new_with_model(GTK_TREE_MODEL(bfwin->bookmarkstore));
749
cell = gtk_cell_renderer_text_new();
750
column = gtk_tree_view_column_new_with_attributes("", cell, "text", NAME_COLUMN, NULL);
751
gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
752
gtk_tree_view_append_column(GTK_TREE_VIEW(bfwin->bmark), column);
753
gtk_widget_show_all(bfwin->bmark);
754
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(bfwin->bmark), FALSE);
755
/*gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(bfwin->bmark), TRUE);*/
756
scroll = gtk_scrolled_window_new(NULL, NULL);
757
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
758
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll), bfwin->bmark);
759
gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 0);
760
g_signal_connect(G_OBJECT(bfwin->bmark), "button-press-event",
761
G_CALLBACK(bmark_event_mouseclick), bfwin);
762
gtk_tree_view_expand_all(bfwin->bmark);
768
* bmark_get_iter_at_tree_position:
770
* determine bookmark's location in the tree and insert - result GtkTreeIter is stored in m->iter
772
static void bmark_get_iter_at_tree_position(Tbfwin * bfwin, Tbmark * m) {
775
DEBUG_MSG("bmark_get_iter_at_tree_position, started for filepath=%s\n",m->filepath);
776
if (!bfwin->bmark_files) {
777
DEBUG_MSG("bmark_get_iter_at_tree_position, creating hashtable for bfwin=%p\n",bfwin);
778
bfwin->bmark_files = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
780
ptr = g_hash_table_lookup(bfwin->bmark_files, m->filepath);
781
if (ptr == NULL) { /* closed document or bookmarks never set */
783
parent = g_new0(GtkTreeIter, 1);
784
gtk_tree_store_append(bfwin->bookmarkstore, parent, NULL);
785
switch (main_v->props.bookmarks_filename_mode) {
787
g_strdup(m->filepath);
789
case BM_FMODE_HOME: /* todo */
790
if (bfwin->project != NULL && bfwin->project->basedir && strlen(bfwin->project->basedir)) {
791
gint baselen = strlen(bfwin->project->basedir);
792
if (strncmp(m->filepath, bfwin->project->basedir, baselen)==0) {
793
title = g_strdup(m->filepath + baselen);
797
/* case BM_FMODE_FILE:
798
title = g_path_get_basename(m->filepath);
802
title = g_path_get_basename(m->filepath);
804
gtk_tree_store_set(bfwin->bookmarkstore, parent, NAME_COLUMN, title, PTR_COLUMN, m->doc, -1);
807
if (m->doc != NULL) {
808
DEBUG_MSG("bmark_get_iter_at_tree_position, setting parent iter %p for doc%p\n",parent,m->doc);
809
m->doc->bmark_parent = parent;
811
DEBUG_MSG("bmark_get_iter_at_tree_position, appending parent %p in hashtable for filepath=%s\n",parent, m->filepath);
812
/* the hash table frees the key, but not the value, on destroy */
813
g_hash_table_insert(bfwin->bmark_files, g_strdup(m->filepath), parent);
815
parent = (GtkTreeIter *) ptr;
818
Tbmark *bef = bmark_find_bookmark_before_offset(bfwin, m->offset, parent);
820
gtk_tree_store_prepend(bfwin->bookmarkstore, &m->iter, parent);
823
gtk_tree_store_insert_after(GTK_TREE_STORE(bfwin->bookmarkstore),&m->iter,parent,&bef->iter);
830
because we don't store them in a hashtable anymore, it's no problem to have
831
bookmarks with the same name
832
static gboolean bmark_name_exists(Tdocument * doc, const gchar * name)
837
if (doc->bmark_parent == NULL)
840
gtk_tree_model_iter_children(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &tmpiter,
844
gtk_tree_model_get(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &tmpiter, PTR_COLUMN,
847
if (strcmp(mark->name, name) == 0)
850
cont = gtk_tree_model_iter_next(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &tmpiter);
857
* this function should create the global
858
* main_v->bookmarkstore
862
main_v->bookmarkstore = gtk_tree_store_new(N_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER);
863
DEBUG_MSG("bmark_init, created main_v->bookmarkstore at %p\n", main_v->bookmarkstore);
864
main_v->bmarkdata = g_new0(Tbmarkdata, 1);
868
/* this function will load the bookmarks
869
* from bfwin->session->bmarks and parse
870
* them into treestore bfwin->bookmarkstore
872
* this function should ALSO check all dcouments that are
873
* opened (bfwin->documentlist) if they have bookmarks !!
875
void bmark_reload(Tbfwin * bfwin)
877
GList *tmplist = g_list_first(bfwin->session->bmarks);
878
DEBUG_MSG("bmark_reload for bfwin %p\n",bfwin);
879
if (bfwin->bmark_files != NULL)
880
g_hash_table_destroy(bfwin->bmark_files);
881
bfwin->bmark_files = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
883
gchar **items = (gchar **) tmplist->data;
884
if (items && count_array(items) == 6) {
887
b = g_new0(Tbmark, 1);
888
b->name = g_strdup(items[0]);
889
b->description = g_strdup(items[1]);
890
b->filepath = g_strdup(items[2]);
891
b->offset = atoi(items[3]);
892
b->text = g_strdup(items[4]);
893
b->len = atoi(items[5]);
895
bmark_get_iter_at_tree_position(bfwin, b);
896
if (b->name && strlen(b->name)>0) {
897
ptr = g_strconcat(b->name, " - ", b->text, NULL);
899
ptr = g_strdup(b->text);
901
gtk_tree_store_set(bfwin->bookmarkstore, &(b->iter), NAME_COLUMN, ptr, PTR_COLUMN, b,
905
tmplist = g_list_next(tmplist);
908
tmplist = g_list_first(bfwin->documentlist);
910
DEBUG_MSG("bmark_reload, calling bmark_set_for_doc for doc=%p\n",tmplist->data);
911
bmark_set_for_doc(DOCUMENT(tmplist->data));
912
bmark_check_length(bfwin, DOCUMENT(tmplist->data));
913
tmplist = g_list_next(tmplist);
918
* this function will simply call
919
* gtk_tree_view_set_model() to connect the treeview
920
* to the new treestore, used in unloading and
921
* loading of projects
923
void bmark_set_store(Tbfwin * bfwin) {
924
DEBUG_MSG("bmark_set_store set store %p for bfwin %p\n",bfwin->bookmarkstore,bfwin);
925
if (bfwin->bookmarkstore && bfwin->bmark) {
926
gtk_tree_view_set_model(bfwin->bmark, GTK_TREE_MODEL(bfwin->bookmarkstore));
930
void bmark_clean_for_doc(Tdocument * doc) {
934
if (doc->bmark_parent == NULL)
936
DEBUG_MSG("bmark_clean_for_doc, getting children for parent_iter=%p\n",doc->bmark_parent);
938
gtk_tree_model_iter_children(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &tmpiter,
942
DEBUG_MSG("bmark_clean_for_doc, getting bookmark for first child\n");
943
gtk_tree_model_get(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &tmpiter, PTR_COLUMN,
946
bmark_update_offset_from_textmark(b);
947
DEBUG_MSG("bmark_clean_for_doc, bookmark=%p, new offset=%d, now deleting GtkTextMark from TextBuffer\n",b,b->offset);
948
gtk_text_buffer_delete_mark(doc->buffer, b->mark);
952
bmark_store(doc->bfwin, b);
955
cont = gtk_tree_model_iter_next(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &tmpiter);
957
/* now unset the Tdocument* in the second column */
958
DEBUG_MSG("bmark_clean_for_doc, unsetting and freeing parent_iter %p for doc %p\n",doc->bmark_parent,doc);
959
gtk_tree_store_set(GTK_TREE_STORE(BFWIN(doc->bfwin)->bookmarkstore), doc->bmark_parent, PTR_COLUMN, NULL, -1);
960
/* remove the pointer from the hastable */
961
g_hash_table_remove(BFWIN(doc->bfwin)->bmark_files,doc->filename);
962
g_free(doc->bmark_parent);
963
doc->bmark_parent = NULL;
967
* this function will check is this document needs any bookmarks, and set the
968
* doc->bmark_parent if needed
970
void bmark_set_for_doc(Tdocument * doc) {
974
if (!doc->filename) {
975
DEBUG_MSG("bmark_set_for_doc, document %p does not have a filename, returning\n", doc);
978
DEBUG_MSG("bmark_set_for_doc, doc=%p, filename=%s\n",doc,doc->filename);
979
/* if (!BFWIN(doc->bfwin)->bmark) {
980
DEBUG_MSG("bmark_set_for_doc, no leftpanel, not implemented yet!!\n");
983
if (doc->bmark_parent) {
984
DEBUG_MSG("this document (%p) already has a bmark_parent (%p) why is this function called?\n",doc,doc->bmark_parent);
989
gtk_tree_model_iter_children(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &tmpiter,
993
if (gtk_tree_model_iter_children
994
(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &child, &tmpiter)) {
996
gtk_tree_model_get(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &child, PTR_COLUMN,
999
if (strcmp(mark->filepath, doc->filename) == 0) { /* this is it */
1001
DEBUG_MSG("bmark_set_for_doc, we found a bookmark for document %s at offset=%d!\n",doc->filename,mark->offset);
1002
/* we will now first set the Tdocument * into the second column of the parent */
1003
gtk_tree_store_set(GTK_TREE_STORE(BFWIN(doc->bfwin)->bookmarkstore), &tmpiter, PTR_COLUMN, doc, -1);
1006
gtk_text_buffer_get_iter_at_offset(doc->buffer, &it, mark->offset);
1007
mark->mark = gtk_text_buffer_create_mark(doc->buffer, NULL, &it, TRUE);
1009
gtk_tree_model_iter_next(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore),
1013
gtk_tree_model_get(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &child,
1014
PTR_COLUMN, &mark, -1);
1017
DEBUG_MSG("bmark_set_for_doc, next bookmark at offset=%d!\n",mark->offset);
1018
gtk_text_buffer_get_iter_at_offset(doc->buffer, &it, mark->offset);
1020
gtk_text_buffer_create_mark(doc->buffer, NULL, &it, TRUE);
1023
gtk_tree_model_iter_next(GTK_TREE_MODEL
1024
(BFWIN(doc->bfwin)->bookmarkstore), &child);
1026
doc->bmark_parent = g_memdup(&tmpiter, sizeof(GtkTreeIter));
1027
DEBUG_MSG("bmark_set_for_doc, added parent_iter %p to doc %p\n",doc->bmark_parent,doc);
1032
cont = gtk_tree_model_iter_next(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &tmpiter);
1034
DEBUG_MSG("bmark_set_for_doc, no bookmarks found for document %s\n", doc->filename);
1038
* bmark_get_bookmarked_lines:
1040
* @ fromit: GtkTextIter *
1041
* @ toit: GtkTextIter *
1043
* this function returns a hash table with all bookmarks between fromit and toit
1045
* this function is called VERY OFTEN (might be 20X per second!!!!) by document.c
1046
* to redraw the bookmarks at the sides
1047
* so we obviously need to keep this function VERY FAST
1049
* the function will return NULL if no bookmarks for this document are
1050
* known (this is faster then looking in an empty hash table)
1052
* Return value: #GHashTable * pointer or NULL
1054
GHashTable *bmark_get_bookmarked_lines(Tdocument * doc, GtkTextIter *fromit, GtkTextIter *toit) {
1055
if (doc->bmark_parent) {
1056
gboolean cont = TRUE;
1059
GtkTreeIter tmpiter;
1061
GHashTable *ret = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
1063
/* because the bookmarks are sorted by line number, we don't have to scan trough all
1064
bookmarks, we can start at the bookmark *before* fromit, and continue until the
1065
first bookmark > toit */
1066
offset = gtk_text_iter_get_offset(fromit);
1067
mark = bmark_find_bookmark_before_offset(BFWIN(doc->bfwin), offset, doc->bmark_parent);
1069
tmpiter = mark->iter;
1071
cont = gtk_tree_model_iter_children(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore),
1072
&tmpiter, doc->bmark_parent);
1077
gtk_tree_model_get(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &tmpiter, PTR_COLUMN,
1079
if (mark && mark->mark) {
1082
gtk_text_buffer_get_iter_at_mark(doc->buffer, &it, mark->mark);
1083
if (gtk_text_iter_compare(toit,&it) < 0) {
1085
} else if (gtk_text_iter_compare(fromit,&it) < 0) {
1086
iaux = g_new(gint, 1);
1087
*iaux = gtk_text_iter_get_line(&it);
1088
g_hash_table_insert(ret, iaux, g_strdup(mark->is_temp ? "1" : "0"));
1091
cont = gtk_tree_model_iter_next(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &tmpiter);
1098
/* this function will simply add the bookmark as defined in the arguments
1100
* will use offset if itoffset is NULL
1101
* will use itoffset if not NULL
1103
static void bmark_add_backend(Tdocument *doc, GtkTextIter *itoffset, gint offset, const gchar *name, const gchar *text, gboolean is_temp) {
1105
gchar *displaytext = NULL;
1107
m = g_new0(Tbmark, 1);
1112
m->offset = gtk_text_iter_get_offset(&it);
1114
gtk_text_buffer_get_iter_at_offset(doc->buffer,&it,offset);
1118
m->mark = gtk_text_buffer_create_mark(doc->buffer, NULL, &it, TRUE);
1119
m->filepath = g_strdup(doc->filename);
1120
m->is_temp = is_temp;
1121
m->text = g_strdup(text);
1122
m->name = (name) ? g_strdup(name) : g_strdup("");
1123
m->description = g_strdup("");
1125
/* insert into tree */
1126
bmark_get_iter_at_tree_position(doc->bfwin, m);
1127
displaytext = bmark_display_text(m->name, m->text);
1128
gtk_tree_store_set(BFWIN(doc->bfwin)->bookmarkstore, &m->iter, NAME_COLUMN, displaytext, PTR_COLUMN, m, -1);
1129
g_free (displaytext);
1133
bmark_store(BFWIN(doc->bfwin), m);
1138
* bmark_text_for_offset:
1140
* will use offset if itoffset is NULL
1141
* will use itoffset if not NULL
1143
static gchar *bmark_text_for_offset(Tdocument *doc, GtkTextIter *itoffset, gint offset) {
1144
GtkTextIter it, eit, sit;
1148
gtk_text_buffer_get_iter_at_offset(doc->buffer,&it,offset);
1151
gtk_text_iter_forward_to_line_end(&eit);
1152
gtk_text_iter_forward_chars(&sit, BMARK_SHOW_NUM_TEXT_CHARS);
1153
if (!gtk_text_iter_in_range(&sit, &it, &eit))
1157
gchar *tmp = gtk_text_iter_get_text(&it, &sit);
1158
DEBUG_MSG("bmark_text_for_offset, text=%s\n",tmp);
1162
return gtk_text_iter_get_text(&it, &sit);
1165
/* this function will add a bookmark to the current document at current cursor / selection */
1166
static void bmark_add_current_doc_backend(Tbfwin *bfwin, const gchar *name, gint offset, gboolean is_temp) {
1167
GtkTextIter it, eit, sit;
1168
DEBUG_MSG("bmark_add_backend, adding bookmark at offset=%d for bfwin=%p\n",offset,bfwin);
1169
/* create bookmark */
1170
gtk_text_buffer_get_iter_at_offset(DOCUMENT(bfwin->current_document)->buffer,&it,offset);
1171
/* if there is a selection, and the offset is within the selection, we'll use it as text content */
1172
if (gtk_text_buffer_get_selection_bounds(DOCUMENT(bfwin->current_document)->buffer,&sit,&eit)
1173
&& gtk_text_iter_in_range(&it,&sit,&eit)) {
1174
gchar *text = gtk_text_iter_get_text(&sit, &eit);
1175
bmark_add_backend(DOCUMENT(bfwin->current_document), &sit, offset, name, text, is_temp);
1180
text = bmark_text_for_offset(DOCUMENT(bfwin->current_document), &it, offset);
1181
bmark_add_backend(DOCUMENT(bfwin->current_document), &it, offset, name, text, is_temp);
1185
/* only if there is a left panel we should do this */
1186
gtk_tree_view_expand_all(bfwin->bmark);
1187
gtk_widget_grab_focus(bfwin->current_document->view);
1192
can we make this function faster? when adding bookmarks from a search this function uses
1193
a lot of time, perhaps that can be improved
1195
static Tbmark *bmark_get_bmark_at_line(Tdocument *doc, gint offset) {
1196
GtkTextIter sit, eit;
1197
GtkTreeIter tmpiter;
1199
gtk_text_buffer_get_iter_at_offset(doc->buffer,&sit,offset);
1200
linenum = gtk_text_iter_get_line(&sit);
1202
gtk_text_iter_set_line_offset(&sit, 0);
1203
gtk_text_iter_forward_to_line_end(&eit);
1206
gchar *tmp = gtk_text_buffer_get_text(doc->buffer, &sit,&eit,FALSE);
1207
DEBUG_MSG("bmark_get_bmark_at_line, searching bookmarks at line %d between offsets %d - %d --> '%s'\n",linenum,gtk_text_iter_get_offset(&sit),gtk_text_iter_get_offset(&eit),tmp);
1211
/* check for existing bookmark in this place */
1212
if (DOCUMENT(doc)->bmark_parent) {
1215
m = bmark_find_bookmark_before_offset(BFWIN(doc->bfwin), offset, doc->bmark_parent);
1217
DEBUG_MSG("bmark_get_bmark_at_line, m=NULL, get first child\n");
1218
if (gtk_tree_model_iter_children(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &tmpiter,doc->bmark_parent)) {
1219
gtk_tree_model_get(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &tmpiter, PTR_COLUMN, &m2, -1);
1220
gtk_text_buffer_get_iter_at_mark(doc->buffer, &testit,m2->mark);
1221
if (gtk_text_iter_get_line(&testit) == linenum) {
1226
gtk_text_buffer_get_iter_at_mark(doc->buffer, &testit,m->mark);
1227
DEBUG_MSG("bmark_get_bmark_at_line, m=%p, has linenum=%d\n",m,gtk_text_iter_get_line(&testit));
1228
if (gtk_text_iter_get_line(&testit) == linenum) {
1232
if (gtk_tree_model_iter_next(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore),&tmpiter)) {
1233
gtk_tree_model_get(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &tmpiter, PTR_COLUMN, &m2, -1);
1234
gtk_text_buffer_get_iter_at_mark(doc->buffer, &testit,m2->mark);
1235
if (gtk_text_iter_get_line(&testit) == linenum) {
1240
DEBUG_MSG("bmark_get_bmark_at_line, nothing found at this line, return NULL\n");
1244
DEBUG_MSG("bmark_get_bmark_at_line, no existing bookmark found, return NULL\n");
1250
* @doc: a #Tdocument* with the document
1251
* @offset: the character position where to set the bookmark
1252
* @name: a name to set for the bookmark, or NULL for no name
1253
* @text: the text for the bookmark, or NULL to have it set automatically
1255
* Code in bluefish that want to set a bookmark, not related to
1256
* the cursor location or a mouse position should use
1259
void bmark_add_extern(Tdocument *doc, gint offset, const gchar *name, const gchar *text, gboolean is_temp) {
1260
DEBUG_MSG("adding bookmark at offset %d with name %s\n",offset,name); /* dummy */
1261
if (!bmark_get_bmark_at_line(doc, offset)) {
1263
bmark_add_backend(doc, NULL, offset, (name) ? name : "", text, is_temp);
1265
gchar *tmp = bmark_text_for_offset(doc, NULL, offset);
1266
bmark_add_backend(doc, NULL, offset, (name) ? name : "", tmp, is_temp);
1272
void bmark_add(Tbfwin * bfwin) {
1276
/* check for unnamed document */
1277
if (!DOCUMENT(bfwin->current_document)->filename) {
1278
error_dialog(bfwin->main_window, _("Add bookmark"),
1279
_("Cannot add bookmarks in unnamed files."));
1280
/*\nPlease save the file first. A Save button in this dialog would be cool -- Alastair*/
1283
/* if the left panel is disabled, we simply should add the bookmark to the list, and do nothing else */
1284
/* if (bfwin->bmark == NULL) {
1285
DEBUG_MSG("no left panel, this is not implemented yet\n");
1288
im = gtk_text_buffer_get_insert(DOCUMENT(bfwin->current_document)->buffer);
1289
gtk_text_buffer_get_iter_at_mark(DOCUMENT(bfwin->current_document)->buffer, &it, im);
1290
offset = gtk_text_iter_get_offset(&it);
1292
/* check for existing bookmark in this place */
1293
has_mark = (bmark_get_bmark_at_line(DOCUMENT(bfwin->current_document), offset) != NULL);
1295
info_dialog(bfwin->main_window, _("Add bookmark"),
1296
_("You already have a bookmark here!"));
1299
bmark_add_current_doc_backend(bfwin, "", offset, !main_v->props.bookmarks_default_store);
1303
gboolean bmark_have_bookmark_at_stored_bevent(Tdocument * doc) {
1304
if (BMARKDATA(main_v->bmarkdata)->bevent_doc == doc) {
1305
return (bmark_get_bmark_at_line(doc, BMARKDATA(main_v->bmarkdata)->bevent_charoffset) != NULL);
1310
void bmark_store_bevent_location(Tdocument * doc, gint charoffset) {
1311
DEBUG_MSG("bmark_store_bevent_location, storing offset=%d for doc=%p\n",charoffset,doc);
1312
BMARKDATA(main_v->bmarkdata)->bevent_doc = doc;
1313
BMARKDATA(main_v->bmarkdata)->bevent_charoffset = charoffset;
1316
void bmark_del_at_bevent(Tdocument *doc) {
1317
if (BMARKDATA(main_v->bmarkdata)->bevent_doc == doc) {
1318
Tbmark *b = bmark_get_bmark_at_line(doc, BMARKDATA(main_v->bmarkdata)->bevent_charoffset);
1320
DEBUG_MSG("bmark_del_at_bevent, deleting bookmark %p\n",b);
1321
bmark_check_remove(BFWIN(doc->bfwin),b); /* check if we should remove a filename too */
1322
bmark_unstore(BFWIN(doc->bfwin), b);
1328
void bmark_add_at_bevent(Tdocument *doc) {
1329
/* check for unnamed document */
1330
if (!doc->filename) {
1331
error_dialog(BFWIN(doc->bfwin)->main_window, _("Add bookmark"),
1332
_("Cannot add bookmarks in unnamed files."));
1335
if (BMARKDATA(main_v->bmarkdata)->bevent_doc == doc) {
1336
gint offset = BMARKDATA(main_v->bmarkdata)->bevent_charoffset;
1337
/* we have the location */
1338
/*if (BFWIN(doc->bfwin)->bmark == NULL) {
1339
DEBUG_MSG("adding bookmarks without left panel is not implemented yet\n");
1341
bmark_add_current_doc_backend(doc->bfwin, "", offset, !main_v->props.bookmarks_default_store);
1347
void bmark_del_for_filename(Tbfwin *bfwin, gchar *filename) {
1348
GtkTreeIter *parent = (GtkTreeIter *)g_hash_table_lookup(bfwin->bmark_files,filename);
1350
bmark_del_children_backend(bfwin, parent);
1355
void bmark_del_for_document(Tbfwin *bfwin, Tdocument *doc) {
1356
if (doc->bmark_parent) {
1357
bmark_del_children_backend(bfwin, doc->bmark_parent);
1361
void bmark_del_all(Tbfwin *bfwin,gboolean ask) {
1363
gchar *btns[]={GTK_STOCK_NO,GTK_STOCK_YES,NULL};
1364
GtkTreeIter tmpiter;
1366
if (bfwin==NULL) return;
1369
ret = multi_query_dialog(bfwin->main_window,_("Delete all bookmarks."), _("Are you sure?"), 0, 0, btns);
1372
DEBUG_MSG("bmark_del_all, deleting all bookmarks!\n");
1373
while (gtk_tree_model_iter_children(GTK_TREE_MODEL(bfwin->bookmarkstore), &tmpiter, NULL) ) {
1376
gtk_tree_model_get(GTK_TREE_MODEL(bfwin->bookmarkstore), &tmpiter, NAME_COLUMN,&name, -1);
1377
DEBUG_MSG("bmark_del_all, the toplevel has child '%s'\n", name);
1379
bmark_del_children_backend(bfwin, &tmpiter);
1381
gtk_widget_grab_focus(bfwin->current_document->view);
1384
void bmark_check_length(Tbfwin * bfwin, Tdocument * doc) {
1385
GtkTreeIter tmpiter;
1387
if (!doc || !doc->bmark_parent) {
1388
DEBUG_MSG("bmark_check_length, no bmark_parent iter => no bookmarks, returning\n");
1391
DEBUG_MSG("bmark_check_length, doc %p, filename %s\n\n", doc, doc->filename);
1394
gtk_tree_model_iter_children(GTK_TREE_MODEL(bfwin->bookmarkstore), &tmpiter,
1397
Tbmark *mark = NULL;
1398
gtk_tree_model_get(GTK_TREE_MODEL(BFWIN(doc->bfwin)->bookmarkstore), &tmpiter, PTR_COLUMN,
1402
#ifdef HAVE_GNOME_VFS
1403
size = doc->fileinfo->size;
1405
size = doc->statbuf.st_size;
1407
DEBUG_MSG("bmark_check_length, bmark has %d, file has %ld\n",mark->len, size);
1408
if (mark->len != size) {
1410
gchar *btns[]={GTK_STOCK_NO,GTK_STOCK_YES,NULL};
1412
str = g_strconcat(_("File size changed in file\n"),doc->filename,NULL);
1413
ret = multi_query_dialog(bfwin->main_window,_("Bookmarks positions could be incorrect. Delete bookmarks?"), str, 0, 0, btns);
1415
bmark_del_for_document(bfwin, doc);
1420
DEBUG_MSG("bmark_check_length, NOT GOOD no mark in the treestore??\n");
1422
cont = gtk_tree_model_iter_next(GTK_TREE_MODEL(bfwin->bookmarkstore), &tmpiter);
1424
DEBUG_MSG("bmark_check_length, all bookmarks OK, returning\n");
1427
void bmark_cleanup(Tbfwin * bfwin) {
1428
DEBUG_MSG("bmark_cleanup, cleanup for bfwin=%p\n",bfwin);
1429
/* we are not destroying a store, so let's not destroy tree positions, it seems, they
1430
are recovered from store - Oskar */
1431
/* if (bfwin->bmark_files) g_hash_table_destroy(bfwin->bmark_files);
1432
bfwin->bmark_files = NULL; */
1434
bfwin->bmark = NULL;