diff --git a/ChangeLog b/ChangeLog index 61c25626..0fc671c5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2008-06-12 Nick Treleaven + + * src/plugindata.h, src/document.c, src/plugins.c, src/document.h, + src/symbols.c: + Note: this breaks the plugin API for document functions. + Make all DocumentFuncs use a GeanyDocument* instead of an integer + index, so there's no need to access the documents array or (in most + cases) use DOC_IDX_VALID() - just check for non-NULL. + Add GeanyDocument::index field for use with the documents array. + Add DOC_IDX() macro to get the document index from a possibly NULL + pointer. + Note: the new functions in the core have a documents_ prefix where + they would conflict with the old names, which are still present and + used in the core (but will be removed soon). + Remove DocumentFuncs::get_cur_idx() - use get_current() instead. + Replace DocumentFuncs::get_n_idx() with get_from_page(). + Rename DocumentFuncs::find_by_realpath() to find_by_real_path(). + Replace DocumentFuncs::remove() with remove_page(). + Add 'changed' argument for DocumentFuncs::set_text_changed(). + Add dox for document_set_filetype(). + Rename debugging function doc() doc_at() to avoid conflicts. + Rename document_find_by_realpath() in the core also. + + 2008-06-11 Enrico Tröger * tagmanager/python.c: diff --git a/src/document.c b/src/document.c index 8918f84b..8424110a 100644 --- a/src/document.c +++ b/src/document.c @@ -112,18 +112,16 @@ static gboolean update_type_keywords(ScintillaObject *sci, gint lang); * @param realname The filename to search, which should be identical to the * string returned by @c tm_get_real_path(). * - * @return The %document index which has the given filename or @c -1 - * if no document was found. + * @return The matching document, or NULL. * @note This is only really useful when passing a @c TMWorkObject::file_name. * @see document_find_by_filename(). **/ -gint document_find_by_realpath(const gchar *realname) +GeanyDocument* documents_find_by_real_path(const gchar *realname) { guint i; - gint ret = -1; if (! realname) - return -1; /* file doesn't exist on disk */ + return NULL; /* file doesn't exist on disk */ for (i = 0; i < documents_array->len; i++) { @@ -133,11 +131,10 @@ gint document_find_by_realpath(const gchar *realname) if (filenamecmp(realname, doc->real_path) == 0) { - ret = i; - break; + return doc; } } - return ret; + return NULL; } @@ -160,56 +157,52 @@ static gchar *get_real_path_from_utf8(const gchar *utf8_filename) * * @param utf8_filename The filename to search (in UTF-8 encoding). * - * @return The %document index which has the given filename or @c -1 - * if no document was found. - * @see document_find_by_realpath(). + * @return The matching document, or NULL. + * @see document_find_by_real_path(). **/ -gint document_find_by_filename(const gchar *utf8_filename) +GeanyDocument *documents_find_by_filename(const gchar *utf8_filename) { guint i; - gint ret = -1; + GeanyDocument *doc; + gchar *realname; if (! utf8_filename) - return -1; + return NULL; /* First search GeanyDocument::file_name, so we can find documents with a * filename set but not saved on disk, like vcdiff produces */ for (i = 0; i < documents_array->len; i++) { - GeanyDocument *doc = documents[i]; + doc = documents[i]; if (! documents[i]->is_valid || doc->file_name == NULL) continue; if (filenamecmp(utf8_filename, doc->file_name) == 0) { - ret = i; - break; + return doc; } } - if (ret == -1) - { - /* Now try matching based on the realpath(), which is unique per file on disk */ - gchar *realname = get_real_path_from_utf8(utf8_filename); - - ret = document_find_by_realpath(realname); - g_free(realname); - } - return ret; + /* Now try matching based on the realpath(), which is unique per file on disk */ + realname = get_real_path_from_utf8(utf8_filename); + doc = documents_find_by_real_path(realname); + g_free(realname); + return doc; } -/* returns the document index which has sci */ -gint document_find_by_sci(ScintillaObject *sci) +/* returns the document which has sci, or NULL. */ +GeanyDocument *documents_find_by_sci(ScintillaObject *sci) { guint i; - if (! sci) return -1; + if (! sci) return NULL; - for(i = 0; i < documents_array->len; i++) + for (i = 0; i < documents_array->len; i++) { - if (documents[i]->is_valid && documents[i]->sci == sci) return i; + if (documents[i]->is_valid && documents[i]->sci == sci) + return documents[i]; } - return -1; + return NULL; } @@ -228,40 +221,19 @@ gint document_get_notebook_page(gint doc_idx) * * @param page_num The notebook page number to search. * - * @return The index of the given notebook page @a page_num in the %document list or @c -1 - * if no documents are opened. + * @return The corresponding document for the given notebook page, or NULL. **/ -gint document_get_n_idx(guint page_num) +GeanyDocument *document_get_from_page(guint page_num) { ScintillaObject *sci; - if (page_num >= documents_array->len) return -1; + + if (page_num >= documents_array->len) + return NULL; sci = (ScintillaObject*)gtk_notebook_get_nth_page( GTK_NOTEBOOK(main_widgets.notebook), page_num); - return document_find_by_sci(sci); -} - - -/** - * Find and retrieve the index of the current %document. - * - * @return The index of the current notebook page in the %document list or @c -1 - * if no documents are opened. - **/ -gint document_get_cur_idx() -{ - gint cur_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(main_widgets.notebook)); - - if (cur_page == -1) - return -1; - else - { - ScintillaObject *sci = (ScintillaObject*) - gtk_notebook_get_nth_page(GTK_NOTEBOOK(main_widgets.notebook), cur_page); - - return document_find_by_sci(sci); - } + return documents_find_by_sci(sci); } @@ -270,11 +242,19 @@ gint document_get_cur_idx() * * @return A pointer to the current %document or @c NULL if there are no opened documents. **/ -GeanyDocument *document_get_current() +GeanyDocument *document_get_current(void) { - gint idx = document_get_cur_idx(); + gint cur_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(main_widgets.notebook)); - return DOC_IDX_VALID(idx) ? documents[idx] : NULL; + if (cur_page == -1) + return NULL; + else + { + ScintillaObject *sci = (ScintillaObject*) + gtk_notebook_get_nth_page(GTK_NOTEBOOK(main_widgets.notebook), cur_page); + + return documents_find_by_sci(sci); + } } @@ -295,11 +275,19 @@ void document_finalize() * according to the document's save state. * This is called by Geany mostly when opening or saving files. * - * @param idx The %document index to operate on. + * @param doc The document to use. + * @param changed Whether the document state should indicate changes have been made. **/ -void document_set_text_changed(gint idx) +void documents_set_text_changed(GeanyDocument *doc, gboolean changed) { - if (DOC_IDX_VALID(idx) && ! main_status.quitting) + gint idx = DOC_IDX(doc); + + if (! DOC_IDX_VALID(idx)) + return; + + documents[idx]->changed = changed; + + if (! main_status.quitting) { ui_update_tab_status(idx); ui_save_buttons_toggle(documents[idx]->changed); @@ -484,6 +472,7 @@ static gint document_create(const gchar *utf8_filename) } this = documents[new_idx]; init_doc_struct(this); /* initialize default document settings */ + this->index = new_idx; this->file_name = g_strdup(utf8_filename); @@ -524,7 +513,7 @@ static gint document_create(const gchar *utf8_filename) * * @return @a TRUE if the document was actually removed or @a FALSE otherwise. **/ -gboolean document_remove(guint page_num) +gboolean document_remove_page(guint page_num) { gint idx = document_get_n_idx(page_num); @@ -609,9 +598,9 @@ gint document_new_file_if_non_open() * @param ft The filetype to set or @c NULL to detect it from @a filename if not @c NULL. * @param text The initial content of the file (in UTF-8 encoding), or @c NULL. * - * @return The index of the new file in @ref documents_array. + * @return The new document. **/ -gint document_new_file(const gchar *filename, GeanyFiletype *ft, const gchar *text) +GeanyDocument *documents_new_file(const gchar *filename, GeanyFiletype *ft, const gchar *text) { gint idx = document_create(filename); @@ -668,7 +657,7 @@ gint document_new_file(const gchar *filename, GeanyFiletype *ft, const gchar *te msgwin_status_add(_("New file \"%s\" opened."), (documents[idx]->file_name != NULL) ? documents[idx]->file_name : GEANY_STRING_UNTITLED); - return idx; + return documents[idx]; } @@ -689,14 +678,14 @@ gint document_new_file(const gchar *filename, GeanyFiletype *ft, const gchar *te * @param ft The %filetype for the %document or @c NULL to auto-detect the %filetype. * @param forced_enc The file encoding to use or @c NULL to auto-detect the file encoding. * - * @return The index of the opened file or -1 if an error occurred. + * @return The document opened or NULL. **/ -gint document_open_file(const gchar *locale_filename, gboolean readonly, +GeanyDocument *documents_open_file(const gchar *locale_filename, gboolean readonly, GeanyFiletype *ft, const gchar *forced_enc) { - /* This is a wrapper for document_open_file_full(). - * Do not use this when opening multiple files (unless using document_delay_colourise()). */ - return document_open_file_full(-1, locale_filename, 0, readonly, ft, forced_enc); + gint idx = document_open_file_full(-1, locale_filename, 0, readonly, ft, forced_enc); + + return DOC_IDX_VALID(idx) ? documents[idx] : NULL; } @@ -1216,8 +1205,6 @@ void document_open_file_list(const gchar *data, gssize length) * @param readonly Whether to open the %document in read-only mode. * @param ft The %filetype for the %document or @c NULL to auto-detect the %filetype. * @param forced_enc The file encoding to use or @c NULL to auto-detect the file encoding. - * - * @return The index of the opened file or -1 if an error occurred. **/ void document_open_files(const GSList *filenames, gboolean readonly, GeanyFiletype *ft, const gchar *forced_enc) @@ -1238,14 +1225,15 @@ void document_open_files(const GSList *filenames, gboolean readonly, GeanyFilety * Reloads the %document with the given index @a idx with the specified file encoding * @a forced_enc or @c NULL to auto-detect the file encoding. * - * @param idx The %document index for the file to reload. + * @param doc The document to reload. * @param forced_enc The file encoding to use or @c NULL to auto-detect the file encoding. * * @return @a TRUE if the %document was actually reloaded or @a FALSE otherwise. **/ -gboolean document_reload_file(gint idx, const gchar *forced_enc) +gboolean documents_reload_file(GeanyDocument *doc, const gchar *forced_enc) { gint pos = 0; + gint idx = DOC_IDX(doc); if (! DOC_IDX_VALID(idx)) return FALSE; @@ -1448,16 +1436,17 @@ static gint write_data_to_disk(gint idx, const gchar *data, gint len) * * If the file is not modified, this functions does nothing unless force is set to @c TRUE. * - * @param idx The %document index for the file to save. + * @param doc The %document to save. * @param force Whether to save the file even if it is not modified (e.g. for Save As). * * @return @c TRUE if the file was saved or @c FALSE if the file could not or should not be saved. **/ -gboolean document_save_file(gint idx, gboolean force) +gboolean documents_save_file(GeanyDocument *doc, gboolean force) { gchar *data; gsize len; gint err; + gint idx = DOC_IDX(doc); if (! DOC_IDX_VALID(idx)) return FALSE; @@ -2128,11 +2117,14 @@ static gboolean update_type_keywords(ScintillaObject *sci, gint lang) } -/* sets the filetype of the document (sets syntax highlighting and tagging) */ -void document_set_filetype(gint idx, GeanyFiletype *type) +/** Sets the filetype of the document (which controls syntax highlighting and tags) + * @param doc The document to use. + * @param type The filetype. */ +void documents_set_filetype(GeanyDocument *doc, GeanyFiletype *type) { gboolean colourise = FALSE; gboolean ft_changed; + gint idx = DOC_IDX(doc); if (type == NULL || ! DOC_IDX_VALID(idx)) return; @@ -2179,11 +2171,13 @@ void document_set_filetype(gint idx, GeanyFiletype *type) * This function only set the encoding of the %document, it does not any conversions. The new * encoding is used when e.g. saving the file. * - * @param idx The index of the %document. + * @param doc The %document to use. * @param new_encoding The encoding to be set for the %document. **/ -void document_set_encoding(gint idx, const gchar *new_encoding) +void documents_set_encoding(GeanyDocument *doc, const gchar *new_encoding) { + gint idx = DOC_IDX(doc); + if (! DOC_IDX_VALID(idx) || new_encoding == NULL || utils_str_equal(new_encoding, documents[idx]->encoding)) return; @@ -2464,9 +2458,10 @@ GdkColor *document_get_status_color(gint idx) } -/* useful debugging function (usually debug macros aren't enabled) */ +/* useful debugging function (usually debug macros aren't enabled so can't use + * documents[idx]) */ #ifdef GEANY_DEBUG -GeanyDocument *doc(gint idx) +GeanyDocument *doc_at(gint idx) { return DOC_IDX_VALID(idx) ? documents[idx] : NULL; } @@ -2633,3 +2628,103 @@ gboolean document_close_all(void) } +/* temporary compatibility functions */ + +gint document_new_file(const gchar *filename, GeanyFiletype *ft, const gchar *text) +{ + GeanyDocument *doc = documents_new_file(filename, ft, text); + + return DOC_IDX(doc); +} + + +gint document_get_cur_idx() +{ + GeanyDocument *doc = document_get_current(); + + return DOC_IDX(doc); +} + + +gint document_find_by_sci(ScintillaObject *sci) +{ + GeanyDocument *doc = documents_find_by_sci(sci); + + return DOC_IDX(doc); +} + + +gint document_get_n_idx(guint page_num) +{ + GeanyDocument *doc = document_get_from_page(page_num); + + return DOC_IDX(doc); +} + + +gint document_find_by_filename(const gchar *utf8_filename) +{ + GeanyDocument *doc = documents_find_by_filename(utf8_filename); + + return DOC_IDX(doc); +} + + +gint document_find_by_real_path(const gchar *realname) +{ + GeanyDocument *doc = documents_find_by_real_path(realname); + + return DOC_IDX(doc); +} + + +gboolean document_save_file(gint idx, gboolean force) +{ + if (DOC_IDX_VALID(idx)) + return documents_save_file(documents[idx], force); + return FALSE; +} + + +gint document_open_file(const gchar *locale_filename, gboolean readonly, + GeanyFiletype *ft, const gchar *forced_enc) +{ + GeanyDocument *doc = documents_open_file(locale_filename, readonly, ft, forced_enc); + + return DOC_IDX(doc); +} + + +gboolean document_remove(guint page_num) +{ + return document_remove_page(page_num); +} + + +gboolean document_reload_file(gint idx, const gchar *forced_enc) +{ + if (DOC_IDX_VALID(idx)) + return documents_reload_file(documents[idx], forced_enc); + return FALSE; +} + + +void document_set_encoding(gint idx, const gchar *new_encoding) +{ + if (DOC_IDX_VALID(idx)) + documents_set_encoding(documents[idx], new_encoding); +} + + +void document_set_filetype(gint idx, GeanyFiletype *type) +{ + if (DOC_IDX_VALID(idx)) + documents_set_filetype(documents[idx], type); +} + + +void document_set_text_changed(gint idx) +{ + if (DOC_IDX_VALID(idx)) + documents_set_text_changed(documents[idx], documents[idx]->changed); +} diff --git a/src/document.h b/src/document.h index 4bad0888..b2c35a8c 100644 --- a/src/document.h +++ b/src/document.h @@ -24,8 +24,11 @@ /** * @file document.h * Document related actions: new, save, open, etc. - * Also Scintilla search actions. + * + * @note Currently some functions have a @c documents_ prefix instead of @c document_. + * This is temporary - plugins should still use the p_document-> syntax for those functions. **/ +/* Also Scintilla search actions - but these should probably be moved to search.c. */ #ifndef GEANY_DOCUMENT_H @@ -68,6 +71,7 @@ typedef struct GeanyDocument { /** General flag to represent this document is active and all properties are set correctly. */ gboolean is_valid; + gint index; /**< Index in the documents array. */ /** Whether this %document support source code symbols(tags) to show in the sidebar. */ gboolean has_tags; /** The UTF-8 encoded file name. @@ -126,6 +130,10 @@ extern GPtrArray *documents_array; **/ #define documents ((GeanyDocument **)documents_array->pdata) +/** NULL-safe way to get the index of @a doc_ptr in the documents array. */ +#define DOC_IDX(doc_ptr) \ + (doc_ptr ? doc_ptr->index : -1) + /** * DOC_IDX_VALID checks whether the passed index points to a valid %document object by checking * important properties. It returns FALSE if the index is not valid and then this index @@ -135,7 +143,7 @@ extern GPtrArray *documents_array; ((doc_idx) >= 0 && (guint)(doc_idx) < documents_array->len && documents[doc_idx]->is_valid) /** - * DOC_FILENAME) returns the filename of the %document corresponding to the passed index or + * DOC_FILENAME returns the filename of the %document corresponding to the passed index or * GEANY_STRING_UNTITLED (e.g. _("untitled")) if the %document's filename was not yet set. * This macro never returns NULL. **/ @@ -144,20 +152,46 @@ extern GPtrArray *documents_array; GEANY_STRING_UNTITLED) +/* These functions will replace the older functions. For now they have a documents_ prefix. */ + +GeanyDocument* documents_new_file(const gchar *filename, GeanyFiletype *ft, + const gchar *text); + +GeanyDocument* documents_find_by_filename(const gchar *utf8_filename); + +GeanyDocument* documents_find_by_real_path(const gchar *realname); + +gboolean documents_save_file(GeanyDocument *doc, gboolean force); + +GeanyDocument* documents_open_file(const gchar *locale_filename, gboolean readonly, + GeanyFiletype *ft, const gchar *forced_enc); + +gboolean documents_reload_file(GeanyDocument *doc, const gchar *forced_enc); + +void documents_set_encoding(GeanyDocument *doc, const gchar *new_encoding); + +void documents_set_text_changed(GeanyDocument *doc, gboolean changed); + +void documents_set_filetype(GeanyDocument *doc, GeanyFiletype *type); + + + gint document_find_by_filename(const gchar *utf8_filename); -gint document_find_by_realpath(const gchar *realname); +gint document_find_by_real_path(const gchar *realname); gint document_find_by_sci(ScintillaObject *sci); gint document_get_notebook_page(gint doc_idx); +GeanyDocument* document_get_from_page(guint page_num); + gint document_get_n_idx(guint page_num); -gint document_get_cur_idx(void); - GeanyDocument *document_get_current(void); +gint document_get_cur_idx(void); + void document_init_doclist(void); void document_finalize(void); @@ -166,6 +200,8 @@ void document_set_text_changed(gint idx); void document_apply_update_prefs(gint idx); +gboolean document_remove_page(guint page_num); + gboolean document_remove(guint page_num); gboolean document_account_for_unsaved(void); diff --git a/src/plugindata.h b/src/plugindata.h index e6124df2..534d19b0 100644 --- a/src/plugindata.h +++ b/src/plugindata.h @@ -36,12 +36,12 @@ /* The API version should be incremented whenever any plugin data types below are * modified or appended to. */ -static const gint api_version = 68; +static const gint api_version = 69; /* 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 = 37; +static const gint abi_version = 38; /** Check the plugin can be loaded by Geany. * This performs runtime checks that try to ensure: @@ -201,22 +201,22 @@ GeanyFunctions; /* See document.h */ typedef struct DocumentFuncs { - gint (*new_file) (const gchar *filename, struct GeanyFiletype *ft, const gchar *text); - gint (*get_cur_idx) (void); - gint (*get_n_idx) (guint i); - gint (*find_by_filename) (const gchar *utf8_filename); - gint (*find_by_realpath) (const gchar *realname); - struct GeanyDocument* (*get_current) (void); - gboolean (*save_file) (gint idx, gboolean force); - gint (*open_file) (const gchar *locale_filename, gboolean readonly, + struct GeanyDocument* (*new_file) (const gchar *filename, struct GeanyFiletype *ft, + const gchar *text); + struct GeanyDocument* (*get_current) (void); + struct GeanyDocument* (*get_from_page) (guint page_num); + struct GeanyDocument* (*find_by_filename) (const gchar *utf8_filename); + struct GeanyDocument* (*find_by_real_path) (const gchar *realname); + gboolean (*save_file) (struct GeanyDocument *doc, gboolean force); + struct GeanyDocument* (*open_file) (const gchar *locale_filename, gboolean readonly, struct GeanyFiletype *ft, const gchar *forced_enc); - void (*open_files) (const GSList *filenames, gboolean readonly, struct GeanyFiletype *ft, - const gchar *forced_enc); - gboolean (*remove) (guint page_num); - gboolean (*reload_file) (gint idx, const gchar *forced_enc); - void (*set_encoding) (gint idx, const gchar *new_encoding); - void (*set_text_changed) (gint idx); - void (*set_filetype) (gint idx, struct GeanyFiletype *type); + void (*open_files) (const GSList *filenames, gboolean readonly, + struct GeanyFiletype *ft, const gchar *forced_enc); + gboolean (*remove_page) (guint page_num); + gboolean (*reload_file) (struct GeanyDocument *doc, const gchar *forced_enc); + void (*set_encoding) (struct GeanyDocument *doc, const gchar *new_encoding); + void (*set_text_changed) (struct GeanyDocument *doc, gboolean changed); + void (*set_filetype) (struct GeanyDocument *doc, struct GeanyFiletype *type); } DocumentFuncs; diff --git a/src/plugins.c b/src/plugins.c index f48b2102..ff023694 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -94,20 +94,19 @@ static void pm_show_dialog(GtkMenuItem *menuitem, gpointer user_data); static DocumentFuncs doc_funcs = { - &document_new_file, - &document_get_cur_idx, - &document_get_n_idx, - &document_find_by_filename, - &document_find_by_realpath, + &documents_new_file, &document_get_current, - &document_save_file, - &document_open_file, + &document_get_from_page, + &documents_find_by_filename, + &documents_find_by_real_path, + &documents_save_file, + &documents_open_file, &document_open_files, - &document_remove, - &document_reload_file, - &document_set_encoding, - &document_set_text_changed, - &document_set_filetype + &document_remove_page, + &documents_reload_file, + &documents_set_encoding, + &documents_set_text_changed, + &documents_set_filetype }; static EditorFuncs editor_funcs = { diff --git a/src/symbols.c b/src/symbols.c index 47a2c409..636b5762 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -1197,7 +1197,7 @@ gboolean symbols_goto_tag(const gchar *name, gboolean definition) if (tmtag != NULL) { - gint new_idx = document_find_by_realpath( + gint new_idx = document_find_by_real_path( tmtag->atts.entry.file->work_object.file_name); /* not found in opened document, should open */