From 274058eb7ae290678103390569c5fc11cf7d4fdc Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Tue, 11 Sep 2007 15:21:11 +0000 Subject: [PATCH] Neaten up the plugin API: Make document_open_file() now wrap document_open_file_full(), without the idx for reloading or pos arguments. Replace str_replace() with string_replace_all() in the plugin API. Add utils_string_replace_all(), taking a GString argument. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@1868 ea778897-0a13-0410-b9d1-a72fbfd435f5 --- ChangeLog | 13 +++++ plugins/classbuilder.c | 129 ++++++++++++++++++++--------------------- plugins/export.c | 38 ++++++------ src/callbacks.c | 2 +- src/document.c | 17 ++++-- src/document.h | 5 +- src/keyfile.c | 2 +- src/main.c | 2 +- src/msgwindow.c | 4 +- src/plugindata.h | 9 +-- src/plugins.c | 2 +- src/socket.c | 2 +- src/ui_utils.c | 2 +- src/utils.c | 35 ++++++++++- src/utils.h | 4 ++ src/win32.c | 4 +- 16 files changed, 163 insertions(+), 107 deletions(-) diff --git a/ChangeLog b/ChangeLog index 09533ccf5..f765c6524 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2007-09-11 Nick Treleaven + + * plugins/export.c, plugins/classbuilder.c, src/utils.c, src/win32.c, + src/utils.h, src/plugindata.h, src/msgwindow.c, src/callbacks.c, + src/keyfile.c, src/document.c, src/plugins.c, src/document.h, + src/main.c, src/socket.c, src/ui_utils.c: + Neaten up the plugin API: + Make document_open_file() now wrap document_open_file_full(), + without the idx for reloading or pos arguments. + Replace str_replace() with string_replace_all() in the plugin API. + Add utils_string_replace_all(), taking a GString argument. + + 2007-09-10 Enrico Tröger * THANKS, pixmaps/geany.ico, pixmaps/geany.png: diff --git a/plugins/classbuilder.c b/plugins/classbuilder.c index 0900b5387..1dc204f6c 100644 --- a/plugins/classbuilder.c +++ b/plugins/classbuilder.c @@ -251,102 +251,97 @@ utils_free_pointers(gpointer first, ...) static gchar* get_template_class_header(ClassInfo *class_info) { + gchar *fileheader = NULL; + GString *template = NULL; + switch (class_info->type) { case GEANY_CLASS_TYPE_CPP: - { - gchar *fileheader = NULL; - gchar *template; - - fileheader = templates->get_template_fileheader(GEANY_FILETYPES_C, class_info->header); - template = g_strdup(templates_cpp_class_header); - template = utils->str_replace(template, "{fileheader}", fileheader); - template = utils->str_replace(template, "{header_guard}", class_info->header_guard); - template = utils->str_replace(template, "{base_include}", class_info->base_include); - template = utils->str_replace(template, "{class_name}", class_info->class_name); - template = utils->str_replace(template, "{base_decl}", class_info->base_decl); - template = utils->str_replace(template, "{constructor_decl}", + fileheader = templates->get_template_fileheader(GEANY_FILETYPES_CPP, class_info->header); + template = g_string_new(templates_cpp_class_header); + utils->string_replace_all(template, "{fileheader}", fileheader); + utils->string_replace_all(template, "{header_guard}", class_info->header_guard); + utils->string_replace_all(template, "{base_include}", class_info->base_include); + utils->string_replace_all(template, "{class_name}", class_info->class_name); + utils->string_replace_all(template, "{base_decl}", class_info->base_decl); + utils->string_replace_all(template, "{constructor_decl}", class_info->constructor_decl); - template = utils->str_replace(template, "{destructor_decl}", + utils->string_replace_all(template, "{destructor_decl}", class_info->destructor_decl); + break; - return template; - } case GEANY_CLASS_TYPE_GTK: - { - gchar *fileheader = NULL; - gchar *template; - fileheader = templates->get_template_fileheader(GEANY_FILETYPES_C, class_info->header); - template = g_strdup(templates_gtk_class_header); - template = utils->str_replace(template, "{fileheader}", fileheader); - template = utils->str_replace(template, "{header_guard}", class_info->header_guard); - template = utils->str_replace(template, "{base_include}", class_info->base_include); - template = utils->str_replace(template, "{class_name}", class_info->class_name); - template = utils->str_replace(template, "{class_name_up}", class_info->class_name_up); - template = utils->str_replace(template, "{class_name_low}", class_info->class_name_low); - template = utils->str_replace(template, "{base_name}", class_info->base_name); - template = utils->str_replace(template, "{constructor_decl}", + template = g_string_new(templates_gtk_class_header); + utils->string_replace_all(template, "{fileheader}", fileheader); + utils->string_replace_all(template, "{header_guard}", class_info->header_guard); + utils->string_replace_all(template, "{base_include}", class_info->base_include); + utils->string_replace_all(template, "{class_name}", class_info->class_name); + utils->string_replace_all(template, "{class_name_up}", class_info->class_name_up); + utils->string_replace_all(template, "{class_name_low}", class_info->class_name_low); + utils->string_replace_all(template, "{base_name}", class_info->base_name); + utils->string_replace_all(template, "{constructor_decl}", class_info->constructor_decl); - - return template; - } + break; } - return NULL; + g_free(fileheader); + + if (template) + return g_string_free(template, FALSE); + else + return NULL; } + static gchar* get_template_class_source(ClassInfo *class_info) { + gchar *fileheader = NULL; + GString *template = NULL; + switch (class_info->type) { case GEANY_CLASS_TYPE_CPP: - { - gchar *fileheader = NULL; - gchar *template; - - fileheader = templates->get_template_fileheader(GEANY_FILETYPES_C, class_info->source); - template = g_strdup(templates_cpp_class_source); - template = utils->str_replace(template, "{fileheader}", fileheader); - template = utils->str_replace(template, "{header}", class_info->header); - template = utils->str_replace(template, "{class_name}", class_info->class_name); - template = utils->str_replace(template, "{base_include}", class_info->base_include); - template = utils->str_replace(template, "{base_name}", class_info->base_name); - template = utils->str_replace(template, "{constructor_impl}", + fileheader = templates->get_template_fileheader(GEANY_FILETYPES_CPP, class_info->source); + template = g_string_new(templates_cpp_class_source); + utils->string_replace_all(template, "{fileheader}", fileheader); + utils->string_replace_all(template, "{header}", class_info->header); + utils->string_replace_all(template, "{class_name}", class_info->class_name); + utils->string_replace_all(template, "{base_include}", class_info->base_include); + utils->string_replace_all(template, "{base_name}", class_info->base_name); + utils->string_replace_all(template, "{constructor_impl}", class_info->constructor_impl); - template = utils->str_replace(template, "{destructor_impl}", + utils->string_replace_all(template, "{destructor_impl}", class_info->destructor_impl); + break; - return template; - } case GEANY_CLASS_TYPE_GTK: - { - gchar *fileheader = NULL; - gchar *template; - fileheader = templates->get_template_fileheader(GEANY_FILETYPES_C, class_info->source); - template = g_strdup(templates_gtk_class_source); - template = utils->str_replace(template, "{fileheader}", fileheader); - template = utils->str_replace(template, "{header}", class_info->header); - template = utils->str_replace(template, "{class_name}", class_info->class_name); - template = utils->str_replace(template, "{class_name_up}", class_info->class_name_up); - template = utils->str_replace(template, "{class_name_low}", class_info->class_name_low); - template = utils->str_replace(template, "{base_name}", class_info->base_name); - template = utils->str_replace(template, "{base_gtype}", class_info->base_gtype); - template = utils->str_replace(template, "{destructor_decl}", class_info->destructor_decl); - template = utils->str_replace(template, "{constructor_impl}", + template = g_string_new(templates_gtk_class_source); + utils->string_replace_all(template, "{fileheader}", fileheader); + utils->string_replace_all(template, "{header}", class_info->header); + utils->string_replace_all(template, "{class_name}", class_info->class_name); + utils->string_replace_all(template, "{class_name_up}", class_info->class_name_up); + utils->string_replace_all(template, "{class_name_low}", class_info->class_name_low); + utils->string_replace_all(template, "{base_name}", class_info->base_name); + utils->string_replace_all(template, "{base_gtype}", class_info->base_gtype); + utils->string_replace_all(template, "{destructor_decl}", class_info->destructor_decl); + utils->string_replace_all(template, "{constructor_impl}", class_info->constructor_impl); - template = utils->str_replace(template, "{destructor_impl}", + utils->string_replace_all(template, "{destructor_impl}", class_info->destructor_impl); - template = utils->str_replace(template, "{gtk_destructor_registration}", + utils->string_replace_all(template, "{gtk_destructor_registration}", class_info->gtk_destructor_registration); - - return template; - } + break; } - return NULL; + g_free(fileheader); + + if (template) + return g_string_free(template, FALSE); + else + return NULL; } diff --git a/plugins/export.c b/plugins/export.c index bd8270d64..04cdaa1b5 100644 --- a/plugins/export.c +++ b/plugins/export.c @@ -275,7 +275,7 @@ static void write_data(const gchar *filename, const gchar *data) } -static gchar *get_date(gint type) +static const gchar *get_date(gint type) { static gchar str[128]; gchar *format; @@ -346,10 +346,10 @@ static void write_latex_file(gint idx, const gchar *filename, gboolean use_zoom) gchar c, c_next, *tmp; // 0 - fore, 1 - back, 2 - bold, 3 - italic, 4 - font size, 5 - used(0/1) gint styles[STYLE_MAX + 1][MAX_TYPES]; - gchar *latex; gboolean block_open = FALSE; GString *body; GString *cmds; + GString *latex; // first read all styles from Scintilla for (i = 0; i <= STYLE_MAX; i++) @@ -526,20 +526,20 @@ static void write_latex_file(gint idx, const gchar *filename, gboolean use_zoom) } // write all - latex = g_strdup(TEMPLATE_LATEX); - latex = utils->str_replace(latex, "{export_content}", body->str); - latex = utils->str_replace(latex, "{export_styles}", cmds->str); - latex = utils->str_replace(latex, "{export_date}", get_date(DATE_TYPE_DEFAULT)); + latex = g_string_new(TEMPLATE_LATEX); + utils->string_replace_all(latex, "{export_content}", body->str); + utils->string_replace_all(latex, "{export_styles}", cmds->str); + utils->string_replace_all(latex, "{export_date}", get_date(DATE_TYPE_DEFAULT)); if (doc_list[idx].file_name == NULL) - latex = utils->str_replace(latex, "{export_filename}", GEANY_STRING_UNTITLED); + utils->string_replace_all(latex, "{export_filename}", GEANY_STRING_UNTITLED); else - latex = utils->str_replace(latex, "{export_filename}", doc_list[idx].file_name); + utils->string_replace_all(latex, "{export_filename}", doc_list[idx].file_name); - write_data(filename, latex); + write_data(filename, latex->str); g_string_free(body, TRUE); g_string_free(cmds, TRUE); - g_free(latex); + g_string_free(latex, TRUE); } @@ -550,12 +550,12 @@ static void write_html_file(gint idx, const gchar *filename, gboolean use_zoom) // 0 - fore, 1 - back, 2 - bold, 3 - italic, 4 - font size, 5 - used(0/1) gint styles[STYLE_MAX + 1][MAX_TYPES]; gboolean span_open = FALSE; - gchar *html; const gchar *font_name; gint font_size; PangoFontDescription *font_desc; GString *body; GString *css; + GString *html; // first read all styles from Scintilla for (i = 0; i <= STYLE_MAX; i++) @@ -677,21 +677,21 @@ static void write_html_file(gint idx, const gchar *filename, gboolean use_zoom) } // write all - html = g_strdup(TEMPLATE_HTML); - html = utils->str_replace(html, "{export_date}", get_date(DATE_TYPE_HTML)); - html = utils->str_replace(html, "{export_content}", body->str); - html = utils->str_replace(html, "{export_styles}", css->str); + html = g_string_new(TEMPLATE_HTML); + utils->string_replace_all(html, "{export_date}", get_date(DATE_TYPE_HTML)); + utils->string_replace_all(html, "{export_content}", body->str); + utils->string_replace_all(html, "{export_styles}", css->str); if (doc_list[idx].file_name == NULL) - html = utils->str_replace(html, "{export_filename}", GEANY_STRING_UNTITLED); + utils->string_replace_all(html, "{export_filename}", GEANY_STRING_UNTITLED); else - html = utils->str_replace(html, "{export_filename}", doc_list[idx].file_name); + utils->string_replace_all(html, "{export_filename}", doc_list[idx].file_name); - write_data(filename, html); + write_data(filename, html->str); pango_font_description_free(font_desc); g_string_free(body, TRUE); g_string_free(css, TRUE); - g_free(html); + g_string_free(html, TRUE); } diff --git a/src/callbacks.c b/src/callbacks.c index d3a6ddd1b..db0db3337 100644 --- a/src/callbacks.c +++ b/src/callbacks.c @@ -1947,7 +1947,7 @@ on_menu_open_selected_file1_activate (GtkMenuItem *menuitem, } locale_filename = utils_get_locale_from_utf8(filename); - document_open_file(-1, locale_filename, 0, FALSE, NULL, NULL); + document_open_file(locale_filename, FALSE, NULL, NULL); g_free(filename); g_free(locale_filename); diff --git a/src/document.c b/src/document.c index 42310002d..75b22d7ac 100644 --- a/src/document.c +++ b/src/document.c @@ -563,6 +563,15 @@ gint document_new_file(const gchar *filename, filetype *ft, const gchar *text) } +/* This is a wrapper for document_open_file_full(), see that function for details. + * Do not use this when opening multiple files (unless using document_delay_colourise()). */ +gint document_open_file(const gchar *locale_filename, gboolean readonly, + filetype *ft, const gchar *forced_enc) +{ + return document_open_file_full(-1, locale_filename, 0, readonly, ft, forced_enc); +} + + typedef struct { gchar *data; // null-terminated file data @@ -825,7 +834,7 @@ static void set_cursor_position(gint idx, gint pos) * * This avoids unnecessary recolourising, saving significant processing when a lot of files * are open of a filetype that supports user typenames, e.g. C. */ -gint document_open_file(gint idx, const gchar *filename, gint pos, gboolean readonly, +gint document_open_file_full(gint idx, const gchar *filename, gint pos, gboolean readonly, filetype *ft, const gchar *forced_enc) { gint editor_mode; @@ -987,7 +996,7 @@ void document_open_file_list(const gchar *data, gssize length) if (list[i] == NULL) break; filename = g_filename_from_uri(list[i], NULL, NULL); if (filename == NULL) continue; - document_open_file(-1, filename, 0, FALSE, NULL, NULL); + document_open_file(filename, FALSE, NULL, NULL); g_free(filename); } document_colourise_new(); @@ -1007,7 +1016,7 @@ void document_open_files(const GSList *filenames, gboolean readonly, filetype *f for (item = filenames; item != NULL; item = g_slist_next(item)) { - document_open_file(-1, item->data, 0, readonly, ft, forced_enc); + document_open_file(item->data, readonly, ft, forced_enc); } document_colourise_new(); } @@ -1022,7 +1031,7 @@ gint document_reload_file(gint idx, const gchar *forced_enc) // try to set the cursor to the position before reloading pos = sci_get_current_position(doc_list[idx].sci); - return document_open_file(idx, NULL, pos, doc_list[idx].readonly, + return document_open_file_full(idx, NULL, pos, doc_list[idx].readonly, doc_list[idx].file_type, forced_enc); } diff --git a/src/document.h b/src/document.h index 2043ae347..50e42f260 100644 --- a/src/document.h +++ b/src/document.h @@ -127,7 +127,10 @@ gint document_clone(gint old_idx, const gchar *utf8_filename); /* See document.c. */ -gint document_open_file(gint idx, const gchar *filename, gint pos, gboolean readonly, +gint document_open_file(const gchar *locale_filename, gboolean readonly, + filetype *ft, const gchar *forced_enc); + +gint document_open_file_full(gint idx, const gchar *filename, gint pos, gboolean readonly, filetype *ft, const gchar *forced_enc); /* Takes a new line separated list of filename URIs and opens each file. diff --git a/src/keyfile.c b/src/keyfile.c index 711c5c964..dc2b98fb4 100644 --- a/src/keyfile.c +++ b/src/keyfile.c @@ -693,7 +693,7 @@ gboolean configuration_open_files() if (g_file_test(locale_filename, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK)) { filetype *ft = filetypes_get_from_uid(uid); - document_open_file(-1, locale_filename, pos, FALSE, ft, NULL); + document_open_file_full(-1, locale_filename, pos, FALSE, ft, NULL); ret = TRUE; } else diff --git a/src/main.c b/src/main.c index 4649351f5..ac0e20408 100644 --- a/src/main.c +++ b/src/main.c @@ -542,7 +542,7 @@ static gboolean open_cl_files(gint argc, gchar **argv) { gint idx; - idx = document_open_file(-1, filename, 0, FALSE, NULL, NULL); + idx = document_open_file(filename, FALSE, NULL, NULL); // add recent file manually because opening_session_files is set if (DOC_IDX_VALID(idx)) ui_add_recent_file(doc_list[idx].file_name); diff --git a/src/msgwindow.c b/src/msgwindow.c index 6f07e5237..1ce777110 100644 --- a/src/msgwindow.c +++ b/src/msgwindow.c @@ -514,7 +514,7 @@ gboolean msgwin_goto_compiler_file_line() g_free(utf8_filename); if (idx < 0) // file not already open - idx = document_open_file(-1, filename, 0, FALSE, NULL, NULL); + idx = document_open_file(filename, FALSE, NULL, NULL); if (idx >= 0 && doc_list[idx].is_valid) { @@ -788,7 +788,7 @@ gboolean msgwin_goto_messages_file_line() if (filename != NULL && line > -1) { // use document_open_file to find an already open file, or open it in place - idx = document_open_file(-1, filename, 0, FALSE, NULL, NULL); + idx = document_open_file(filename, FALSE, NULL, NULL); // utils_goto_file_line will check valid filename. ret = utils_goto_file_line(filename, FALSE, line); } diff --git a/src/plugindata.h b/src/plugindata.h index a0f775abf..586389303 100644 --- a/src/plugindata.h +++ b/src/plugindata.h @@ -71,12 +71,12 @@ /* The API version should be incremented whenever any plugin data types below are * modified. */ -static const gint api_version = 16; +static const gint api_version = 17; /* The ABI version should be incremented whenever existing fields in the plugin * data types below have to be changed or reordered. It should stay the same if fields * are only appended, as this doesn't affect existing fields. */ -static const gint abi_version = 8; +static const gint abi_version = 9; /* This performs runtime checks that try to ensure: * 1. Geany ABI data types are compatible with this plugin. @@ -174,7 +174,7 @@ typedef struct DocumentFuncs gint (*get_cur_idx) (); struct document* (*get_current) (); gboolean (*save_file)(gint idx, gboolean force); - gboolean (*open_file)(gint idx, const gchar *filename, gint pos, gboolean readonly, + gboolean (*open_file)(const gchar *locale_filename, gboolean readonly, struct filetype *ft, const gchar *forced_enc); void (*open_files)(const GSList *filenames, gboolean readonly, struct filetype *ft, const gchar *forced_enc); @@ -232,7 +232,8 @@ TemplateFuncs; typedef struct UtilsFuncs { gboolean (*str_equal) (const gchar *a, const gchar *b); - gchar* (*str_replace) (gchar *haystack, const gchar *needle, const gchar *replacement); + gboolean (*string_replace_all) (GString *haystack, const gchar *needle, + const gchar *replacement); GSList* (*get_file_list) (const gchar *path, guint *length, GError **error); gint (*write_file) (const gchar *filename, const gchar *text); gchar* (*get_locale_from_utf8) (const gchar *utf8_text); diff --git a/src/plugins.c b/src/plugins.c index deae638a7..376922b76 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -123,7 +123,7 @@ static TemplateFuncs template_funcs = { static UtilsFuncs utils_funcs = { &utils_str_equal, - &utils_str_replace, + &utils_string_replace_all, &utils_get_file_list, &utils_write_file, &utils_get_locale_from_utf8, diff --git a/src/socket.c b/src/socket.c index 993cd323f..096e3c2f0 100644 --- a/src/socket.c +++ b/src/socket.c @@ -420,7 +420,7 @@ gboolean socket_lock_input_cb(GIOChannel *source, GIOCondition condition, gpoint g_strstrip(buf); // remove \n char if (g_file_test(buf, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK)) - document_open_file(-1, buf, 0, FALSE, NULL, NULL); + document_open_file(buf, FALSE, NULL, NULL); else { // create new file if it doesn't exist gint idx; diff --git a/src/ui_utils.c b/src/ui_utils.c index af366cbc2..8d680cb99 100644 --- a/src/ui_utils.c +++ b/src/ui_utils.c @@ -838,7 +838,7 @@ recent_file_activate_cb (GtkMenuItem *menuitem, gchar *utf8_filename = menu_item_get_text(menuitem); gchar *locale_filename = utils_get_locale_from_utf8(utf8_filename); - if (document_open_file(-1, locale_filename, 0, FALSE, NULL, NULL) > -1) + if (document_open_file(locale_filename, FALSE, NULL, NULL) > -1) recent_file_loaded(utf8_filename); g_free(locale_filename); diff --git a/src/utils.c b/src/utils.c index 0cd10d6e7..df53d7436 100644 --- a/src/utils.c +++ b/src/utils.c @@ -805,8 +805,9 @@ For more information read the documentation (in ", doc_dir, DIR_SEP "index.html } -/* replaces all occurrences of needle in haystack with replacement - * all strings have to NULL-terminated and needle and replacement have to be different, +/* Replaces all occurrences of needle in haystack with replacement. + * New code should use utils_string_replace_all() instead. + * All strings have to be NULL-terminated and needle and replacement have to be different, * e.g. needle "%" and replacement "%%" causes an endless loop */ gchar *utils_str_replace(gchar *haystack, const gchar *needle, const gchar *replacement) { @@ -1618,3 +1619,33 @@ gboolean utils_str_has_upper(const gchar *str) } return FALSE; } + + +/* Replaces all occurrences of needle in str with replace. + * Currently this is not safe if replace matches needle. + * Returns: TRUE if needle was found. */ +gboolean utils_string_replace_all(GString *str, const gchar *needle, const gchar *replace) +{ + const gchar *c; + gssize pos = -1; + + g_return_val_if_fail(NZV(needle), FALSE); + g_return_val_if_fail(! NZV(replace) || strstr(replace, needle) == NULL, FALSE); + + while (1) + { + c = strstr(str->str, needle); + if (c == NULL) + break; + else + { + pos = c - str->str; + g_string_erase(str, pos, strlen(needle)); + if (replace) + g_string_insert(str, pos, replace); + } + } + return (pos != -1); +} + + diff --git a/src/utils.h b/src/utils.h index b544addc1..a5b1eafbc 100644 --- a/src/utils.h +++ b/src/utils.h @@ -99,10 +99,14 @@ gchar *utils_get_hostname(); gint utils_make_settings_dir(const gchar *dir, const gchar *data_dir, const gchar *doc_dir); + +gboolean utils_string_replace_all(GString *str, const gchar *needle, const gchar *replace); + gchar *utils_str_replace(gchar *haystack, const gchar *needle, const gchar *replacement); gint utils_strpos(const gchar* haystack, const gchar * needle); + gchar *utils_get_date_time(); gchar *utils_get_date(); diff --git a/src/win32.c b/src/win32.c index 69162f5e9..e8b830673 100644 --- a/src/win32.c +++ b/src/win32.c @@ -311,7 +311,7 @@ gboolean win32_show_file_dialog(gboolean file_open) x = of.nFileOffset - 1; if (x != strlen(fname)) { // open a single file - document_open_file(-1, fname, 0, of.Flags & OFN_READONLY, NULL, NULL); + document_open_file(fname, of.Flags & OFN_READONLY, NULL, NULL); } else { // open multiple files @@ -324,7 +324,7 @@ gboolean win32_show_file_dialog(gboolean file_open) if (! fname[x+1]) break; g_snprintf(file_name, 254, "%s\\%s", fname, fname + x + 1); - document_open_file(-1, file_name, 0, of.Flags & OFN_READONLY, NULL, NULL); + document_open_file(file_name, of.Flags & OFN_READONLY, NULL, NULL); } x++; }