/** * erwin - really simple html editor * Copyright (C) 1999 David Vogler * Copyright (C) 1999-2005 Adrian Reber * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: erwinfunctions.c,v 1.44 2005/01/19 21:07:55 adrian Exp $ * * $Author: adrian $ * * Description: a lot of functions * * $Log: erwinfunctions.c,v $ * Revision 1.44 2005/01/19 21:07:55 adrian * update to use the new save_file function * * Revision 1.43 2004/12/29 20:08:04 adrian * * removed functions for old search dialog * * our buffer changed handler should be called last * * Revision 1.42 2004/12/26 21:37:13 adrian * * finished porting to gtkhtml3 * * fix for bug #11 (now scrolling to found text) * * moved search functions to searchbar.c * * Revision 1.41 2004/12/20 20:09:46 adrian * * removed USE_GTKHTML ifdefs * * started porting erwin to gtkhtml3 * * Revision 1.40 2004/10/26 19:00:30 erwin * searchbar version 1 done * * Revision 1.39 2004/10/03 20:18:01 erwin * more searchbar related changes * * Revision 1.38 2004/09/26 21:07:00 erwin * - more work on the searchbar * * Revision 1.37 2004/07/03 20:14:25 erwin * commit * * Revision 1.36 2004/06/27 17:48:24 erwin * * added drag'n'drop support * * bug fixes * * optimized statusbar handling * * removed unused code * * changed search functions to use gtk_source_iter_forward_search() * * better * * Revision 1.35 2004/06/21 21:45:19 erwin * big commit * it has been a long time without a checkout * we are close to version 0.7 * * Revision 1.34 2004/03/21 21:06:30 erwin * support for gtk 2.4 GtkFileChooserDialog * * Revision 1.33 2004/03/11 21:05:01 erwin * too many changes without commits * * Revision 1.32 2003/11/18 08:52:24 erwin * fix message dialogs * * Revision 1.31 2003/10/30 20:54:06 erwin * syntax highlighting implementation * * Revision 1.30 2003/10/24 13:31:44 erwin * more syntax higlighting related stuff * * Revision 1.29 2003/10/22 15:21:35 erwin * include file mess cleaned up * changed format to indent -kr -i8 -l100 * gtksourceview support * using the GtkMessageWidget with stock icons * */ #ifndef lint static const char vcid[] = "$Id: erwinfunctions.c,v 1.44 2005/01/19 21:07:55 adrian Exp $"; #endif /* lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern GtkWidget *main_window; extern struct font_options font_options; extern GtkWidget *status_bar; gint changed = 1; gint from_beginning = 0; gint close_notebook = -1; GtkTextBuffer *get_text_buffer() { struct document *document; GtkTextBuffer *buffer; if (nr_of_documents == -1) return NULL; document = (g_list_nth(documents, gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_main))))->data; if (document->is_rendered) return NULL; buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(document->text_view)); _DEBUG_ fprintf(stderr, "%s:get_text_buffer:%p\n", PACKAGE, buffer); return buffer; } int count_characters(GtkTextBuffer * buffer) { return gtk_text_buffer_get_char_count(buffer); } void update_statistic(GtkTextBuffer * buffer) { gchar length[64]; gint chars; if (globals.display_statistic) { chars = count_characters(buffer); if (chars == 1) snprintf(length, 63, "%d character", chars); else snprintf(length, 63, "%d characters", chars); add_to_statusbar(length, FALSE); } } void clean_buffer() { GtkTextBuffer *buffer; GtkTextIter start, end; buffer = get_text_buffer(); gtk_text_buffer_get_start_iter(buffer, &start); gtk_text_buffer_get_end_iter(buffer, &end); gtk_text_buffer_delete(buffer, &start, &end); } void focus_text_view() { struct document *document; if (rendered()) return; document = (g_list_nth(documents, gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_main))))->data; gtk_window_set_focus(GTK_WINDOW(main_window), document->text_view); } gboolean rendered() { struct document *document; if (nr_of_documents == -1) return TRUE; document = (g_list_nth(documents, gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_main))))->data; _DEBUG_ fprintf(stderr, "rendered:%d\n", document->is_rendered); return document->is_rendered; } void clean_selected() { GtkTextBuffer *buffer; GtkTextIter start, end; buffer = get_text_buffer(); if (gtk_text_buffer_get_selection_bounds(buffer, &start, &end)) { gtk_text_buffer_delete(buffer, &start, &end); } } void insert_text(char *string, gint length) { GtkTextBuffer *buffer; struct document *document; if (!length) return; document = (g_list_nth(documents, gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_main))))->data; buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(document->text_view)); gtk_text_buffer_create_tag(buffer, NULL, NULL); document->changed = TRUE; gtk_text_buffer_insert_at_cursor(buffer, string, length); } void insert_text_around(struct change change, char *string, gint length) { gchar *buffer; gchar *another_buffer; gint i = 0; struct change help; struct document *document; GtkTextBuffer *g_buffer; GtkTextIter start, end; document = (g_list_nth(documents, gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_main))))->data; document->changed = TRUE; g_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(document->text_view)); help = change; /*now filling another_buffer with the starting tag */ another_buffer = g_malloc(length + 9); another_buffer[0] = '<'; for (i = 1; i < length + 1; i++) another_buffer[i] = string[i - 1]; another_buffer[length + 1] = '>'; another_buffer[length + 2] = '\0'; gtk_text_buffer_get_iter_at_offset(g_buffer, &start, change.start); gtk_text_buffer_get_iter_at_offset(g_buffer, &end, change.end); buffer = gtk_text_buffer_get_text(g_buffer, &start, &end, FALSE); gtk_text_buffer_delete(g_buffer, &start, &end); gtk_text_buffer_insert(g_buffer, &start, another_buffer, -1); gtk_text_buffer_insert(g_buffer, &start, buffer, -1); /*now filling another_buffer with the ending tag */ another_buffer[0] = '<'; another_buffer[1] = '/'; for (i = 2; i < length + 2; i++) another_buffer[i] = string[i - 2]; another_buffer[length + 2] = '>'; another_buffer[length + 3] = '\0'; gtk_text_buffer_insert(g_buffer, &start, another_buffer, -1); move_cursor(length + 3, LEFT); g_free(buffer); g_free(another_buffer); _DEBUG_ fprintf(stderr, "%s:insert_text_around ends\n", PACKAGE); } void copy_to_clipboard(GtkWidget * window) { if (rendered()) return; gtk_text_buffer_copy_clipboard(get_text_buffer(), globals.clipboard); } void cut_to_clipboard(GtkWidget * window) { if (rendered()) return; gtk_text_buffer_cut_clipboard(get_text_buffer(), globals.clipboard, TRUE); } void paste_from_clipboard(GtkWidget * window) { if (rendered()) return; gtk_text_buffer_paste_clipboard(get_text_buffer(), globals.clipboard, NULL, TRUE); } struct change test_selection() { struct change change; gint help = 0; GtkTextBuffer *buffer; GtkTextIter start, end; buffer = get_text_buffer(); if (!gtk_text_buffer_get_selection_bounds(buffer, &start, &end)) { _DEBUG_ fprintf(stderr, "%s:now no selection is made\n", PACKAGE); _DEBUG_ fprintf(stderr, "%s:start: %d:end: %d\n", PACKAGE, gtk_text_iter_get_offset(&start), gtk_text_iter_get_offset(&end)); help = gtk_text_iter_get_offset(&start); change.start = change.end = help; } else { _DEBUG_ fprintf(stderr, "%s:now a selection is made\n", PACKAGE); _DEBUG_ fprintf(stderr, "%s:start: %d:end: %d\n", PACKAGE, gtk_text_iter_get_offset(&start), gtk_text_iter_get_offset(&end)); change.start = 0; change.end = 0; change.start = gtk_text_iter_get_offset(&start); change.end = gtk_text_iter_get_offset(&end); if (change.start > change.end) { help = change.start; change.start = change.end; change.end = help; } } _DEBUG_ fprintf(stderr, "%s:change.start:%d:change.end:%d\n", PACKAGE, change.start, change.end); return change; } gint move_cursor(gint length, ErwinCursor orientation) { //gtk_text_iter_backward_visible_cursor_positions and //gtk_text_iter_forward_visible_cursor_positions could be used here //but current implementation seems to work quite good and //therefore it will not be changed struct change change; GtkTextIter iter, iter2, start, end; GtkTextBuffer *buffer = NULL; buffer = get_text_buffer(); gtk_text_buffer_get_start_iter(buffer, &start); gtk_text_buffer_get_start_iter(buffer, &iter); gtk_text_buffer_get_start_iter(buffer, &iter2); gtk_text_buffer_get_end_iter(buffer, &end); change = test_selection(); gtk_text_iter_set_offset(&iter, change.start); gtk_text_iter_set_offset(&iter2, change.start + length); _DEBUG_ fprintf(stderr, "%s:now moving cursor: %d\n", PACKAGE, length); if (orientation == LEFT) { if (((change.start - length) <= 0) || (length == -1)) gtk_text_buffer_place_cursor(buffer, &start); else { gtk_text_iter_set_offset(&start, change.start - length); gtk_text_buffer_place_cursor(buffer, &start); } _DEBUG_ fprintf(stderr, "%s:LEFT:position is %d\n", PACKAGE, change.start); } if (orientation == RIGHT) { if ((gtk_text_iter_compare(&iter2, &end) >= 0) || (length == -1)) gtk_text_buffer_place_cursor(buffer, &end); else { _DEBUG_ fprintf(stderr, "%s:moving cursor right\n", PACKAGE); gtk_text_iter_set_offset(&end, change.start + length); gtk_text_buffer_place_cursor(buffer, &end); } _DEBUG_ fprintf(stderr, "%s:RIGHT:position is %d\n", PACKAGE, change.start); } else return 42; return 0; } void file_ok_sel(GtkWidget * widget, GtkFileSelection * fs) { GString *only_the_file; only_the_file = g_string_new(""); insert_text(only_the_file->str, only_the_file->len); move_cursor(only_the_file->len, RIGHT); g_string_free(only_the_file, TRUE); gtk_widget_destroy(GTK_WIDGET(fs)); } void img_functions(GtkWidget * window) { GtkWidget *filew; if (rendered()) return; filew = gtk_file_selection_new("Image File selection"); gtk_signal_connect(GTK_OBJECT(filew), "destroy", (GtkSignalFunc) destroy_message, &filew); gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filew)->ok_button), "clicked", (GtkSignalFunc) file_ok_sel, filew); gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filew)-> cancel_button), "clicked", (GtkSignalFunc) gtk_widget_destroy, GTK_OBJECT(filew)); /*gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew), "nothing"); */ gtk_widget_show(filew); } void get_value_1(GtkWidget * widget, GtkWidget * spinner) { GtkSpinButton *spin; spin = GTK_SPIN_BUTTON(spinner); table_values.rows = gtk_spin_button_get_value_as_int(spin); _DEBUG_ fprintf(stderr, "%s:spin button: %d\n", PACKAGE, gtk_spin_button_get_value_as_int(spin)); } void get_value_2(GtkWidget * widget, GtkWidget * spinner) { GtkSpinButton *spin; spin = GTK_SPIN_BUTTON(spinner); table_values.cols = gtk_spin_button_get_value_as_int(spin); _DEBUG_ fprintf(stderr, "%s:spin button: %d\n", PACKAGE, gtk_spin_button_get_value_as_int(spin)); } void quit_program_from_menu() { quit_program(); } gboolean quit_program() { GtkWidget *dialog; if (!rendered()) { if (gtk_text_buffer_get_modified(get_text_buffer())) { _DEBUG_ fprintf(stderr, "%s:text has been changed after save event\n", PACKAGE); dialog = gtk_message_dialog_new(GTK_WINDOW(main_window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, "File has not been saved...\nReally want to quit?"); switch (gtk_dialog_run(GTK_DIALOG(dialog))) { case GTK_RESPONSE_OK: really_quit_program(); //never reached??? _DEBUG_ fprintf(stderr, "%s:never reached???\n", PACKAGE); break; default: break; } gtk_widget_destroy(dialog); return TRUE; } } really_quit_program(); return FALSE; } void really_quit_program() { _DEBUG_ fprintf(stderr, "%s:quit event occured\n", PACKAGE); the_end(); exit(0); } gint delete_event(GtkWidget * widget, GdkEvent * event, gpointer data) { _DEBUG_ fprintf(stderr, "%s:delete event occured\n", PACKAGE); return (TRUE); } void destroy_message(GtkWidget * dialog) { gtk_grab_remove(dialog); gtk_widget_destroy(dialog); } void destroy_table_wizard(GtkWidget * dialog) { gint i = 1, ii = 1; gchar *buffer = NULL; GtkTextIter start, end; clean_selected(); gtk_text_buffer_get_selection_bounds(get_text_buffer(), &start, &end); gtk_text_buffer_get_end_iter(get_text_buffer(), &end); buffer = gtk_text_buffer_get_text(get_text_buffer(), &start, &end, FALSE); gtk_text_buffer_delete(get_text_buffer(), &start, &end); insert_text("\n\n", 9); move_cursor(9, RIGHT); for (i = 1; i <= table_values.rows; i++) { insert_text("\n", 5); move_cursor(5, RIGHT); for (ii = 1; ii <= table_values.cols; ii++) { insert_text("\t\n", 11); if (ii != table_values.cols || ii == 1) { move_cursor(11, RIGHT); } else { move_cursor(4, RIGHT); } if (table_values.cols == 1 && table_values.rows != 1) { move_cursor(1, LEFT); insert_text("\n", 1); if (i == table_values.rows) { move_cursor(7, RIGHT); insert_text("\n", 1); move_cursor(1, RIGHT); } } if (i != table_values.rows && ii == table_values.cols) { move_cursor(8, RIGHT); } if (ii == table_values.cols) { move_cursor(15, RIGHT); } if (table_values.rows != 1 && table_values.cols != 1 && ii == table_values.cols) { move_cursor(4, RIGHT); if (i != table_values.rows) { insert_text("\n", 1); move_cursor(1, RIGHT); } else { move_cursor(7, RIGHT); insert_text("\n", 1); move_cursor(1, RIGHT); } } } insert_text("\n", 6); } insert_text("
\n", 9); gtk_text_buffer_get_end_iter(get_text_buffer(), &end); gtk_text_buffer_insert(get_text_buffer(), &end, buffer, -1); g_free(buffer); gtk_grab_remove(dialog); gtk_widget_destroy(dialog); } void make_highlighted_text_view(struct document *document, GtkTextBuffer * buffer) { GSList *languages = NULL; gpointer blub; int i = 0; document->manager = gtk_source_languages_manager_new(); g_object_ref(document->manager); g_object_set_data_full(G_OBJECT(buffer), "languages-manager", document->manager, (GDestroyNotify) g_object_unref); document->manager = g_object_get_data(G_OBJECT(buffer), "languages-manager"); languages = (GSList *) gtk_source_languages_manager_get_available_languages(document->manager); while ((blub = g_slist_nth_data(languages, i++))) { if (globals.default_highlighting && !strcmp(globals.default_highlighting, gtk_source_language_get_name(blub))) document->language = blub; } g_object_set(G_OBJECT(buffer), "highlight", TRUE, NULL); g_object_get(G_OBJECT(buffer), "highlight", &(document->syntax_highlighting), NULL); gtk_source_buffer_set_language(GTK_SOURCE_BUFFER(buffer), document->language); if (document->syntax_highlighting) add_to_statusbar(gtk_source_language_get_name(document->language), TRUE); else add_to_statusbar(NULL, TRUE); } void _open_file_ok(const gchar * filename) { GtkWidget *scrollbar; struct document *document; gchar erwin[1025]; FILE *fd = NULL; GtkTextBuffer *buffer; GtkTextIter end; gboolean open = TRUE; GtkWidget *label_box; GtkWidget *image; GtkWidget *button; gint display_statistic = globals.display_statistic; gboolean only_open = FALSE; if (!filename) open = FALSE; if (open) { fd = fopen(filename, "r"); _DEBUG_ fprintf(stderr, "%s:filename is set to: %s", PACKAGE, filename); //strcpy(file, filename); if (fd == NULL) { _DEBUG_ fprintf(stderr, "%s:can't open file for reading\n", PACKAGE); display_dialog("Error", "Insufficient permissions\nto read that file"); return; } } if (nr_of_documents == -1) gtk_widget_show(GTK_WIDGET(notebook_html)); else { document = (g_list_nth(documents, gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_main))))->data; //if it is a new document (meaning no text and changes) and a file open //no new widget is created if (document->new_document && open) only_open = TRUE; } if (!only_open) { document = g_malloc(sizeof(struct document)); memset(document, 0, sizeof(struct document)); document->text_view = GTK_WIDGET(gtk_source_view_new()); _DEBUG_ fprintf(stderr, "%s:new 1 text_view : %p\n", PACKAGE, document->text_view); } buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(document->text_view)); if (open) { document->filename = g_string_new(filename); add_to_recent(document->filename->str); update_recent(NULL); document->saved = TRUE; } else { document->saved = FALSE; document->filename = g_string_new("Untitled"); } _DEBUG_ fprintf(stderr, "%s:file %s\n", PACKAGE, document->filename->str); if (!only_open) { gtk_text_buffer_create_tag(buffer, "red_background", "background", "red", NULL); gtk_text_buffer_create_tag(buffer, "yellow_background", "background", "yellow", NULL); document->notebook_child = gtk_hbox_new(FALSE, FALSE); scrollbar = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbar), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(scrollbar), document->text_view); gtk_box_pack_start(GTK_BOX(document->notebook_child), scrollbar, TRUE, TRUE, 0); gtk_widget_show(document->text_view); gtk_widget_show(scrollbar); gtk_widget_show(document->notebook_child); make_dropable(GTK_TEXT_VIEW(document->text_view)); label_box = gtk_hbox_new(FALSE, FALSE); document->notebook_label = gtk_label_new(NULL); gtk_widget_show(document->notebook_label); gtk_box_pack_start(GTK_BOX(label_box), document->notebook_label, TRUE, TRUE, 0); button = gtk_button_new(); image = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); gtk_container_add(GTK_CONTAINER(button), image); gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_widget_show(image); gtk_widget_show(button); gtk_box_pack_start(GTK_BOX(label_box), button, TRUE, TRUE, 0); gtk_widget_show(label_box); document->nr_of_notebook_child = ++nr_of_documents; document->notebook = notebook_main; document->close_file = FALSE; document->is_rendered = FALSE; document->new_document = TRUE; documents = g_list_append(documents, document); make_highlighted_text_view(document, buffer); gtk_notebook_append_page(GTK_NOTEBOOK(notebook_main), document->notebook_child, label_box); gtk_notebook_set_page(GTK_NOTEBOOK(notebook_main), document->nr_of_notebook_child); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(close_file), &document->nr_of_notebook_child); g_signal_connect_after(G_OBJECT(buffer), "changed", G_CALLBACK(buffer_changed), NULL); } gtk_label_set_text(GTK_LABEL(document->notebook_label), g_basename(document->filename->str)); /* disable updating statusbar */ globals.display_statistic = 0; if (open) { activate_highlighting_from_filename(document); gtk_text_buffer_get_start_iter(buffer, &end); while (fgets(erwin, 1024, fd) != NULL) { _DEBUG_ fprintf(stderr, "%s:reading %s", PACKAGE, erwin); gtk_text_buffer_insert(buffer, &end, erwin, -1); } gtk_text_buffer_get_end_iter(buffer, &end); gtk_text_buffer_get_start_iter(buffer, &end); gtk_text_buffer_place_cursor(buffer, &end); gtk_text_buffer_set_modified(buffer, FALSE); fclose(fd); document->new_document = FALSE; } else { if (globals.show_quickstart) body_functions(); } /* revert to previous setting */ globals.display_statistic = display_statistic; set_title_name(); update_statistic(buffer); focus_text_view(); } void open_file_ok(GtkWidget * widget, GtkFileSelection * fs) { GString *blubber; if (nr_of_documents == -1) gtk_widget_show(GTK_WIDGET(notebook_html)); if (is_file_a_directory(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)))) { blubber = g_string_new(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs))); blubber = g_string_append(blubber, "/"); gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), blubber->str); g_string_free(blubber, TRUE); return; } _open_file_ok(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs))); gtk_grab_remove(GTK_WIDGET(fs)); gtk_widget_destroy(GTK_WIDGET(fs)); } void save_file_ok(struct document *document) { if (is_file_readonly(document->filename->str)) { display_dialog("Error", "Insufficient permissions\n to write that file"); return; } save_file(NULL, document); } void new_file() { _open_file_ok(NULL); } void close_message_dialog(GtkWidget * widget, gpointer data) { GtkWidget *dialog = (GtkWidget *) data; gtk_widget_destroy(dialog); } void ungrab_message(GtkWidget * widget, gpointer data) { gtk_grab_remove(widget); } void display_dialog(gchar * title, gchar * message) { GtkWidget *dialog; dialog = gtk_message_dialog_new(GTK_WINDOW(main_window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, message); gtk_window_set_title(GTK_WINDOW(dialog), title); gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy(dialog); } GtkWidget *entry_in_frame(gchar * title, struct frame_entry *frame_entry) { GtkWidget *entry_box; frame_entry->frame = gtk_frame_new(title); entry_box = gtk_hbox_new(TRUE, TRUE); gtk_container_add(GTK_CONTAINER(frame_entry->frame), entry_box); frame_entry->entry = gtk_entry_new(); gtk_editable_set_editable(GTK_EDITABLE(frame_entry->entry), TRUE); gtk_widget_show(frame_entry->entry); gtk_box_pack_start(GTK_BOX(entry_box), frame_entry->entry, FALSE, FALSE, 30); gtk_widget_show(entry_box); gtk_widget_show(frame_entry->frame); return entry_box; } void body_functions() { body_dialog(body_elements); } void legal() { GtkWidget *license_text; GtkWidget *button; GtkWidget *dialog; GtkWidget *hbox; GtkWidget *scroll; GtkTextBuffer *buffer; GtkTextIter iter; dialog = gtk_dialog_new(); gtk_widget_set_usize(GTK_WIDGET(dialog), 650, 300); gtk_signal_connect(GTK_OBJECT(dialog), "destroy", GTK_SIGNAL_FUNC(ungrab_message), NULL); gtk_window_set_title(GTK_WINDOW(dialog), "License"); gtk_container_border_width(GTK_CONTAINER(dialog), 3); button = gtk_button_new_with_label("Make it so!"); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(close_message_dialog), dialog); GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, FALSE, FALSE, 0); gtk_widget_grab_default(button); gtk_widget_show(button); hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0); license_text = gtk_text_view_new(); scroll = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(scroll), license_text); gtk_box_pack_start(GTK_BOX(hbox), scroll, TRUE, TRUE, 0); gtk_text_view_set_editable(GTK_TEXT_VIEW(license_text), FALSE); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(license_text), FALSE); buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(license_text)); gtk_text_buffer_create_tag(buffer, "courier", "family", "courier", NULL); gtk_text_buffer_get_iter_at_offset(buffer, &iter, 0); gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, license, -1, "courier", NULL); gtk_text_view_set_left_margin(GTK_TEXT_VIEW(license_text), 5); gtk_widget_show(license_text); gtk_widget_show(scroll); gtk_widget_show(hbox); gtk_widget_show(dialog); gtk_grab_add(dialog); } void set_title_name_switch_page(int page_num) { GString *title; struct document *document; GtkTextBuffer *buffer; _DEBUG_ fprintf(stderr, "%s:%d\n", PACKAGE, page_num); if (page_num == -1) document = (g_list_nth(documents, gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_main))))->data; else document = (g_list_nth(documents, page_num))->data; _DEBUG_ fprintf(stderr, "%s:filename: %s\n", PACKAGE, document->filename->str); _DEBUG_ fprintf(stderr, "%s:basename: %s\n", PACKAGE, g_basename(document->filename->str)); title = g_string_new(PACKAGE); title = g_string_append(title, " - "); if (document->filename->str[0] != 0) title = g_string_append(title, g_basename(document->filename->str)); else title = g_string_append(title, "Untitled"); if (!document->is_rendered) { buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(document->text_view)); if (gtk_text_buffer_get_modified(buffer)) title = g_string_append(title, " - *"); } gtk_window_set_title(GTK_WINDOW(main_window), title->str); g_string_free(title, TRUE); } void set_title_name() { set_title_name_switch_page(-1); } void buffer_changed(GtkTextBuffer * textbuffer, gpointer user_data) { struct document *document; if (globals.buffer_not_changed) { gtk_text_buffer_set_modified(get_text_buffer(), FALSE); return; } _DEBUG_ fprintf(stderr, "buffer changed\n"); document = (g_list_nth(documents, gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_main))))->data; gtk_text_buffer_set_modified(get_text_buffer(), TRUE); document->new_document = FALSE; set_title_name(); update_statistic(get_text_buffer()); } void ok_body_dialog(GtkWidget * widget, gpointer data) { gchar *title1 = "\n"; gchar *title2 = "\n"; gchar *title3 = "\n\n\n"); if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(body_elements.content_type))) title = g_string_append(title, "\n "); title = g_string_append(title, title2); title = g_string_append(title, gtk_entry_get_text(GTK_ENTRY(body_elements.title.entry))); title = g_string_append(title, title3); title = g_string_append(title, body_options->str); body = title->len; title = g_string_append(title, title4); /* String made... Now inserting */ clean_buffer(); insert_text(title->str, title->len); move_cursor(-1, LEFT); move_cursor(body + 1, RIGHT); /*Freeing memory */ g_string_free(title, TRUE); g_string_free(body_options, TRUE); close_body_dialog(NULL, GTK_WIDGET(data)); update_statistic(get_text_buffer()); } void make_body_options_string(GString * body_options, gchar * text, struct frame_entry *element) { if (strcmp("", (gtk_entry_get_text(GTK_ENTRY(element->entry))))) { body_options = g_string_append(body_options, text); body_options = g_string_append(body_options, gtk_entry_get_text(GTK_ENTRY(element->entry))); body_options = g_string_append(body_options, "\""); } } gboolean does_file_exist(const gchar * filename) { struct stat buf; if (stat(filename, &buf) == -1) return FALSE; return TRUE; } gboolean is_file_readonly(const gchar * filename) { if (strcmp(filename, FILENAME) == 0 || access(filename, F_OK)) return FALSE; return (access(filename, W_OK) != 0); } gboolean is_file_a_directory(const gchar * filename) { struct stat buf; stat(filename, &buf); if (buf.st_mode & S_IFREG) return FALSE; return TRUE; } void insert_symmetric_tag(gchar * tag) { struct change change; GString *together; struct document *document; document = (g_list_nth(documents, gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_main))))->data; gtk_text_buffer_set_modified(get_text_buffer(), TRUE); change = test_selection(); _DEBUG_ fprintf(stderr, "%s:insert_symmetric_tag()\n", PACKAGE); if (!(change.start - change.end)) { _DEBUG_ fprintf(stderr, "%s:insert_symmetric_tag():2\n", PACKAGE); together = g_string_new("<"); together = g_string_append(together, tag); together = g_string_append(together, ">"); insert_text(together->str, together->len); g_string_free(together, TRUE); move_cursor(strlen(tag) + 3, LEFT); } else insert_text_around(change, tag, strlen(tag)); _DEBUG_ fprintf(stderr, "%s:insert_symmetric_tag():3\n", PACKAGE); gtk_window_set_focus(GTK_WINDOW(main_window), document->text_view); } void body_img_function(GtkWidget * window) { GtkWidget *filew; gtk_grab_remove(body_elements.dialog); filew = gtk_file_selection_new("Image File selection"); gtk_signal_connect(GTK_OBJECT(filew), "destroy", (GtkSignalFunc) destroy_message, &filew); gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filew)->ok_button), "clicked", (GtkSignalFunc) body_img_file_ok_sel, filew); gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filew)->cancel_button), "clicked", (GtkSignalFunc) gtk_widget_destroy, GTK_OBJECT(filew)); gtk_widget_show(filew); } void body_img_file_ok_sel(GtkWidget * widget, GtkWidget * fs) { gtk_entry_set_text(GTK_ENTRY(body_elements.background.entry), g_basename(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)))); gtk_widget_destroy(GTK_WIDGET(fs)); gtk_grab_add(body_elements.dialog); } void href_function_ok(GtkWidget * widget, gpointer data) { GString *new_string; clean_selected(); new_string = g_string_new("entry)))) new_string = g_string_append(new_string, gtk_entry_get_text(GTK_ENTRY (GTK_COMBO(hyperlink.protocol.combo)-> entry))); new_string = g_string_append(new_string, gtk_entry_get_text(GTK_ENTRY(hyperlink.link.entry))); new_string = g_string_append(new_string, "\">"); new_string = g_string_append(new_string, gtk_entry_get_text(GTK_ENTRY(hyperlink.name.entry))); new_string = g_string_append(new_string, ""); /* new string */ insert_text(new_string->str, new_string->len); move_cursor(new_string->len - 4, RIGHT); g_string_free(new_string, TRUE); close_body_dialog(NULL, GTK_WIDGET(data)); focus_text_view(); } GtkWidget *combo_in_frame(gchar * title, struct frame_combo *frame_combo, GList * list_items) { GtkWidget *combo_box; frame_combo->frame = gtk_frame_new(title); combo_box = gtk_hbox_new(TRUE, TRUE); gtk_container_add(GTK_CONTAINER(frame_combo->frame), combo_box); frame_combo->combo = gtk_combo_new(); gtk_combo_set_popdown_strings(GTK_COMBO(frame_combo->combo), list_items); frame_combo->entry = (GTK_COMBO(frame_combo->combo)->entry); gtk_entry_set_editable(GTK_ENTRY(frame_combo->entry), FALSE); gtk_widget_show(frame_combo->combo); gtk_box_pack_start(GTK_BOX(combo_box), frame_combo->combo, FALSE, FALSE, 30); gtk_widget_show(combo_box); gtk_widget_show(frame_combo->frame); return combo_box; } void font_function_ok(GtkWidget * widget, gpointer data) { gchar *title1 = "str); font_ = g_string_append(font_, ">"); if (data) font_ = g_string_append(font_, (gchar *) data);; font_ = g_string_append(font_, title2); /* String made... Now inserting */ _DEBUG_ fprintf(stderr, "%s:%s\n", PACKAGE, font_->str); insert_text(font_->str, font_->len); move_cursor(font_->len - 7, RIGHT); if (data) { g_free(data); } /*Freeing memory */ g_string_free(font_, TRUE); g_string_free(font_option, TRUE); close_body_dialog(NULL, GTK_WIDGET(font_options.dialog)); focus_text_view(); } /** * void switch_page * - this is the callback when the event switch_page occurs * - notebook_label, text, title are set according to the * values retrieved from the GList ... * - new text is focused, if not a gtkhtml widget */ void switch_page(GtkWidget * widget, GtkNotebookPage * page, gint page_num, gpointer user_data) { struct document *document; gpointer blub; int i = 0; GtkTextBuffer *buffer; GtkWidget *disable = NULL; _DEBUG_ fprintf(stderr, "%s:page_num: %d\n", PACKAGE, page_num); if (!nr_of_documents) page_num = 0; _DEBUG_ fprintf(stderr, "%s:length of list: %d\n", PACKAGE, g_list_length(documents)); _DEBUG_ fprintf(stderr, "%s:page_num: %d\n", PACKAGE, page_num); document = (g_list_nth(documents, page_num))->data; //strcpy(file, document->filename->str); set_title_name_switch_page(page_num); _DEBUG_ fprintf(stderr, "%s:document_rendered %d\n", PACKAGE, document->is_rendered); if (!document->is_rendered) { gtk_window_set_focus(GTK_WINDOW(main_window), document->text_view); if (document->syntax_highlighting) add_to_statusbar(gtk_source_language_get_name(document->language), TRUE); else add_to_statusbar(NULL, TRUE); buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(document->text_view)); g_object_set(G_OBJECT(buffer), "highlight", document->syntax_highlighting, NULL); if (document->syntax_highlighting_menuitem) { while ((blub = g_slist_nth_data(highlighting_group, i++))) { GTK_CHECK_MENU_ITEM(blub)->active = FALSE; } GTK_CHECK_MENU_ITEM(document->syntax_highlighting_menuitem)->active = TRUE; } else { while ((blub = g_slist_nth_data(highlighting_group, i++))) { GTK_CHECK_MENU_ITEM(blub)->active = FALSE; } blub = g_slist_nth_data(highlighting_group, i - 2); GTK_CHECK_MENU_ITEM(blub)->active = TRUE; } update_statistic(buffer); } else { while ((blub = g_slist_nth_data(highlighting_group, i++))) { GTK_CHECK_MENU_ITEM(blub)->active = FALSE; } add_to_statusbar(document->filename->str, TRUE); } disable = gtk_item_factory_get_widget(GTK_ITEM_FACTORY(main_factory), "
/Options/Syntax Highlighting/Disable"); g_return_if_fail(GTK_IS_CHECK_MENU_ITEM(disable)); GTK_CHECK_MENU_ITEM(disable)->active = !document->syntax_highlighting; } void close_current_file() { gint page = -1; close_file(NULL, &page); } /** * void close_file * - checking if current document has changed * if yes, then ask user if would like to save file */ gboolean close_file(GtkWidget * widget, gpointer data) { GtkWidget *dialog; gboolean modified = TRUE; gint *page = (gint *) data; struct document *document; close_notebook = *page; if (widget) widget = widget; if (nr_of_documents == -1) return FALSE; if (*page == -1) document = (g_list_nth(documents, gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_main))))->data; else document = (g_list_nth(documents, *page))->data; if (document->is_rendered) modified = FALSE; else { modified = gtk_text_buffer_get_modified(gtk_text_view_get_buffer(GTK_TEXT_VIEW(document-> text_view))); } if (modified) { _DEBUG_ fprintf(stderr, "%s:text has been changed after save event\n", PACKAGE); dialog = gtk_message_dialog_new(GTK_WINDOW(main_window), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "File is not saved.\nSave it now?"); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_NO, GTK_RESPONSE_NO); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK); switch (gtk_dialog_run(GTK_DIALOG(dialog))) { case GTK_RESPONSE_OK: close_ask_yes(document); //never reached??? _DEBUG_ fprintf(stderr, "%s:never reached???\n", PACKAGE); break; case GTK_RESPONSE_NO: close_ask_no(); break; default: break; } gtk_widget_destroy(GTK_WIDGET(dialog)); close_notebook = -1; return TRUE; } really_close_file(); close_notebook = -1; return FALSE; } /** * void switch_html_page * - sets the focus on the text widget */ void switch_html_page() { focus_text_view(); } /** * void really_close_file * - current page of the notebook is removed * and gint nr_of_notebook_child in the GList *documents * gets new values... * - the removed struct document *document is freed * - the new value for gint nr_of_documents is assigned * - GtkWidget *text is NULL if no more documents are opened */ void really_close_file() { gint page_num = close_notebook; struct document *document; if (close_notebook == -1) page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_main)); document = (g_list_nth(documents, page_num))->data; if (!nr_of_documents) { if (document->is_rendered) { _DEBUG_ fprintf(stderr, "%s:document->is_rendered\n", PACKAGE); documents = g_list_remove(documents, document); g_free(document); nr_of_documents--; gtk_notebook_remove_page(GTK_NOTEBOOK(notebook_main), page_num); add_to_statusbar(NULL, FALSE); gtk_window_set_title(GTK_WINDOW(main_window), PACKAGE); return; } else { GSList *languages = NULL; gpointer blub; int i = 0; clean_buffer(); document->filename = g_string_new("Untitled"); document->new_document = TRUE; gtk_text_buffer_set_modified(get_text_buffer(), FALSE); set_title_name(); gtk_label_set_text(GTK_LABEL(document->notebook_label), "Untitled"); //reset highlighting to default document->manager = g_object_get_data(G_OBJECT(get_text_buffer()), "languages-manager"); languages = (GSList *) gtk_source_languages_manager_get_available_languages(document->manager); while ((blub = g_slist_nth_data(languages, i++))) { if (globals.default_highlighting && !strcmp(globals.default_highlighting, gtk_source_language_get_name(blub))) document->language = blub; } g_object_set(G_OBJECT(get_text_buffer()), "highlight", TRUE, NULL); g_object_get(G_OBJECT(get_text_buffer()), "highlight", &(document->syntax_highlighting), NULL); gtk_source_buffer_set_language(GTK_SOURCE_BUFFER(get_text_buffer()), document->language); if (document->syntax_highlighting) add_to_statusbar(gtk_source_language_get_name(document->language), TRUE); else add_to_statusbar(NULL, TRUE); } } if (!nr_of_documents) return; documents = g_list_remove(documents, document); g_free(document); nr_of_documents--; gtk_notebook_remove_page(GTK_NOTEBOOK(notebook_main), page_num); for (page_num = 0; page_num <= nr_of_documents; page_num++) { document = (g_list_nth(documents, page_num))->data; document->nr_of_notebook_child = page_num; } if (nr_of_documents == -1) { gtk_widget_hide(GTK_WIDGET(notebook_html)); } } void close_ask_no() { really_close_file(); } void close_ask_yes(struct document *document) { document->close_file = TRUE; save_file(NULL, document); } void load_done(GtkWidget * html, gpointer data) { struct document *document = (struct document *) data; _DEBUG_ fprintf(stderr, "%s:title_changed %s\n", PACKAGE, gtk_html_get_title(GTK_HTML(html))); if (gtk_html_get_title(GTK_HTML(html)) && strlen(gtk_html_get_title(GTK_HTML(html))) > 0) gtk_label_set_text(GTK_LABEL(((struct document *) (data))->notebook_label), gtk_html_get_title(GTK_HTML(html))); else gtk_label_set_text(GTK_LABEL(((struct document *) (data))->notebook_label), "Untitled"); ((struct document *) (data))->filename = g_string_new(gtk_html_get_title(GTK_HTML(html))); set_title_name_switch_page(document->nr_of_notebook_child); } /* parts copied from the gtkhtml3 test program */ GString *encode_buffer_to_html() { GtkTextBuffer *buffer; GtkTextIter start, end; gchar *erwin = NULL; GString *str = g_string_new(NULL); buffer = get_text_buffer(); gtk_text_buffer_get_start_iter(buffer, &start); gtk_text_buffer_get_end_iter(buffer, &end); erwin = gtk_text_buffer_get_text(buffer, &start, &end, FALSE); _DEBUG_ fprintf(stderr, "%s:%s\n", PACKAGE, erwin); if (strlen(erwin) <= 0) { g_free(erwin); return str; } do { gunichar uc; uc = g_utf8_get_char(erwin); if (uc > 160) g_string_append_printf(str, "&#%u;", uc); else g_string_append_c(str, uc); } while ((erwin = g_utf8_next_char(erwin)) && *erwin); return str; } void on_url(GtkHTML * html, const gchar * url, gpointer data) { if (url) add_to_statusbar((gchar *) url, FALSE); else add_to_statusbar((gchar *) gtk_html_get_title(GTK_HTML(html)), TRUE); } void view_html() { struct document *document; GtkWidget *image; GtkWidget *button; GtkWidget *label_box; GString *html; if (gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_main)) == -1) return; document = (g_list_nth(documents, gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_main))))->data; if (document->is_rendered) return; if (nr_of_documents == -1) gtk_widget_show(GTK_WIDGET(notebook_html)); document = g_malloc(sizeof(struct document)); memset(document, 0, sizeof(struct document)); document->text_view = gtk_html_new(); _DEBUG_ fprintf(stderr, "%s:new 1 text_view : %p\n", PACKAGE, document->text_view); /* setting a default name for the notebook this is probably unnecessary as it will be overwritten in the load_done callback... just to be on the save side */ document->notebook_label = gtk_label_new("Untitled"); document->filename = g_string_new("Untitled"); document->is_rendered = TRUE; document->nr_of_notebook_child = ++nr_of_documents; documents = g_list_append(documents, document); g_signal_connect(G_OBJECT(document->text_view), "load_done", G_CALLBACK(load_done), document); g_signal_connect(G_OBJECT(document->text_view), "on_url", G_CALLBACK(on_url), (gpointer) document); html = encode_buffer_to_html(); /* html is GString containing the text from our buffer */ if (html->len <= 0) { documents = g_list_remove(documents, document); nr_of_documents--; g_free(document); g_string_free(html, TRUE); return; } /* this actually renders our html file */ gtk_html_load_from_string(GTK_HTML(document->text_view), html->str, -1); /* free the GString */ g_string_free(html, TRUE); gtk_widget_show(document->notebook_label); put_in_scrollbar(document); /* this is all for the button on the notebook label */ label_box = gtk_hbox_new(FALSE, FALSE); gtk_box_pack_start(GTK_BOX(label_box), document->notebook_label, TRUE, TRUE, 0); button = gtk_button_new(); image = gtk_image_new_from_stock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU); gtk_container_add(GTK_CONTAINER(button), image); gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_widget_show(image); gtk_widget_show(button); gtk_box_pack_start(GTK_BOX(label_box), button, TRUE, TRUE, 0); gtk_widget_show(label_box); document->notebook = notebook_main; document->changed = TRUE; document->saved = TRUE; document->close_file = FALSE; gtk_notebook_append_page(GTK_NOTEBOOK(notebook_main), document->notebook_child, label_box); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(close_file), &document->nr_of_notebook_child); gtk_notebook_set_page(GTK_NOTEBOOK(notebook_main), document->nr_of_notebook_child); add_to_statusbar(NULL, TRUE); } void put_in_scrollbar(struct document *document) { GtkWidget *scrollbar; document->notebook_child = gtk_hbox_new(FALSE, FALSE); scrollbar = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbar), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(scrollbar), document->text_view); gtk_box_pack_start(GTK_BOX(document->notebook_child), scrollbar, TRUE, TRUE, 0); gtk_widget_show(document->text_view); gtk_widget_show(scrollbar); gtk_widget_show(document->notebook_child); } /** * displays the current message "*message" in the statusbar * every displayed message will be prefixed with "erwin x.x - " * * @param message the message to display * @param new if this is true "*message" is not appended to the current * message but overiding the displayed message */ void add_to_statusbar(gchar * message, gboolean new) { gchar prefix[64]; static gchar *saved_message = NULL; gchar *final_message = NULL; gchar *status_message = NULL; gint context_id = gtk_statusbar_get_context_id(GTK_STATUSBAR(status_bar), "Statusbar"); snprintf(prefix, 63, "%s %s - ", PACKAGE, VERSION); if (!new && message) { if (saved_message) status_message = (gchar *) malloc(strlen(saved_message) + strlen(message) + 4); else status_message = (gchar *) malloc(strlen(message) + 4); status_message[0] = 0; if (saved_message) { strcat(status_message, saved_message); strcat(status_message, " - "); } strcat(status_message, message); } else if (message) { if (saved_message) free(saved_message); status_message = strdup(message); saved_message = strdup(message); } else if (new && !message) { if (saved_message) free(saved_message); saved_message = NULL; } final_message = (gchar *) malloc(strlen(prefix) + ((status_message) ? strlen(status_message) : 0) + 3); final_message[0] = 0; strcat(final_message, prefix); if (status_message) strcat(final_message, status_message); else // -3 removes " - " which is unecessary if no text follows final_message[strlen(final_message) - 3] = 0; gtk_statusbar_push(GTK_STATUSBAR(status_bar), context_id, final_message); free(final_message); } /** * this functions does, by means of magic, close the first * to this cursor position unclosed tag */ void close_tag() { GtkTextBuffer *buffer; GtkTextIter insert, end_start, end_end, start_start, start_end; gchar *result1 = NULL; gchar *result2 = NULL; gchar *temp = NULL; gboolean search = FALSE; GList *previous_tags = NULL; guint length; gint i; gboolean continue_while; buffer = get_text_buffer(); gtk_text_buffer_get_iter_at_mark(buffer, &insert, gtk_text_buffer_get_mark(buffer, "insert")); while (1) { //search for ">" search = gtk_text_iter_backward_search(&insert, ">", GTK_TEXT_SEARCH_TEXT_ONLY, &end_start, &end_end, NULL); //no ">" found means no tag if (!search) break; //if ">" found search for "<" search = gtk_text_iter_backward_search(&end_start, "<", GTK_TEXT_SEARCH_TEXT_ONLY, &start_start, &start_end, NULL); //no "<" found means no tag if (!search) break; //search between "<" and ">" for a " 0) { temp = (g_list_last(previous_tags))->data; previous_tags = g_list_remove(previous_tags, temp); if (temp) free(temp); } if (result1) { insert_text("", 1); free(result1); } } /** * from gnome-vfs-uri.c + changes * to parse the result of a drop event * * @param uri_list a list files created by the drop event * @return a GList where each element is the URI to a file */ GList *uri_list_parse(const gchar * uri_list) { /* Note that this is mostly very stolen from old libgnome/gnome-mime.c */ const gchar *p, *q; gchar *retval; gchar *uri; GList *result = NULL; g_return_val_if_fail(uri_list != NULL, NULL); p = uri_list; /* We don't actually try to validate the URI according to RFC * 2396, or even check for allowed characters - we just ignore * comments and trim whitespace off the ends. We also * allow LF delimination as well as the specified CRLF. */ while (p != NULL) { if (*p != '#') { while (g_ascii_isspace(*p)) p++; q = p; while ((*q != '\0') && (*q != '\n') && (*q != '\r')) q++; if (q > p) { q--; while (q > p && g_ascii_isspace(*q)) q--; retval = g_malloc(q - p + 2); strncpy(retval, p, q - p + 1); retval[q - p + 1] = '\0'; uri = strdup(retval); g_free(retval); if (uri != NULL) result = g_list_prepend(result, uri); } } p = strchr(p, '\n'); if (p != NULL) p++; } return g_list_reverse(result); } /** * callback for the drop event of a drag * no idea what all the parameters mean */ GtkSignalFunc drop_file(GtkWidget * widget, GdkDragContext * context, gint x, gint y, GtkSelectionData * selection_data, guint info, guint time, gpointer user_data) { GList *list = NULL; guint length; int i; list = uri_list_parse(selection_data->data); length = g_list_length(list); for (i = 0; i < length; i++) { // +5 to start after "file:" _open_file_ok(g_list_nth_data(list, i) + 5); free(g_list_nth_data(list, i)); } g_list_free(list); return NULL; } /** * makes the view sensitive to drop events * * @param view the GtkTextView to receive a drop event */ void make_dropable(GtkTextView * view) { static GtkTargetEntry drop_types[] = { {"text/uri-list", 0, 0} }; static gint n_drop_types = sizeof(drop_types) / sizeof(drop_types[0]); GtkTargetList *tl; tl = gtk_drag_dest_get_target_list(GTK_WIDGET(view)); gtk_target_list_add_table(tl, drop_types, n_drop_types); g_signal_connect(G_OBJECT(view), "drag_data_received", G_CALLBACK(drop_file), view); } /** * set the default font * * @param view the GtkTextView which wants the font changed */ void set_view_font(GtkTextView * view) { PangoFontDescription *font_desc; font_desc = pango_font_description_from_string("Mono"); gtk_widget_modify_font(GTK_WIDGET(view), font_desc); pango_font_description_free(font_desc); }