diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 887897a62..8ca9b6cf7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,6 +21,7 @@ concurrency: env: CFLAGS: -g -O2 -Werror=pointer-arith -Werror=implicit-function-declaration CONFIGURE_FLAGS: --disable-silent-rules + CPPCHECKFLAGS: --check-level=exhaustive CCACHE_DIR: ${{ github.workspace }}/.ccache CCACHE_COMPRESS: true CCACHE_MAXSIZE: 1G @@ -36,6 +37,7 @@ jobs: env: CC: ccache gcc CXX: ccache g++ + CPPCHECK_CACHE_PATH: ${{ github.workspace }}/.cppcheck_cache GEANY_SOURCE_PATH: ${{ github.workspace }}/.geany_source GEANY_CACHE_PATH: ${{ github.workspace }}/.geany_cache GEANY_INSTALLATION_PATH: ${{ github.workspace }}/.geany_cache/_geany_install @@ -61,6 +63,15 @@ jobs: id: ccache_cache_timestamp run: echo "timestamp=$(date +%Y-%m-%d-%H-%M)" >> $GITHUB_OUTPUT + - name: Prepare Cppcheck Cache Key + id: prepare_cppcheck_cache_key + run: echo "cppcheck_tag=$(curl -s https://api.github.com/repos/danmar/cppcheck/releases/latest | jq .tag_name)" >> $GITHUB_OUTPUT + + - name: Prepare Geany Cache Key + id: prepare_geany_cache_key + working-directory: ${{ env.GEANY_SOURCE_PATH }} + run: echo "commit_hash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + - name: Configure ccache uses: actions/cache@v4 with: @@ -68,10 +79,12 @@ jobs: key: ${{ runner.os }}-${{ github.job }}-ccache-${{ steps.ccache_cache_timestamp.outputs.timestamp }} restore-keys: ${{ runner.os }}-${{ github.job }}-ccache- - - name: Prepare Geany Cache Key - id: prepare_geany_cache_key - working-directory: ${{ env.GEANY_SOURCE_PATH }} - run: echo "commit_hash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + - name: Configure Cppcheck Cache + id: cppcheck_cache + uses: actions/cache@v4 + with: + path: ${{ env.CPPCHECK_CACHE_PATH }} + key: ${{ runner.os }}-${{ github.job }}-cppcheck-cache-${{ steps.prepare_cppcheck_cache_key.outputs.cppcheck_tag }} - name: Configure Geany Cache id: geany_cache @@ -102,7 +115,6 @@ jobs: # geany-plugins intltool check - cppcheck # debugger libvte-2.91-dev # geanygendoc @@ -126,9 +138,24 @@ jobs: libxml2-dev # spellcheck libenchant-dev + # cppcheck + cmake + libpcre3-dev EOF grep -v '^[ ]*#' $RUNNER_TEMP/dependencies | xargs sudo apt-get install --assume-yes --no-install-recommends + - name: Build cppcheck + if: steps.cppcheck_cache.outputs.cache-hit != 'true' + run: | + mkdir -p ${{ env.CPPCHECK_CACHE_PATH }} + cd ${{ env.CPPCHECK_CACHE_PATH }} + curl -s https://api.github.com/repos/danmar/cppcheck/releases/latest | jq .tarball_url | xargs wget -O cppcheck.tar.gz + tar --strip-components=1 -xf cppcheck.tar.gz + mkdir build + cd build + cmake .. -DHAVE_RULES=On -DUSE_MATCHCOMPILER=On + cmake --build . + - name: Build Geany if: steps.geany_cache.outputs.cache-hit != 'true' run: | @@ -142,6 +169,10 @@ jobs: - name: Configure run: | + # Add previously built cppcheck to $PATH, for this and for succeeding steps + export "PATH=$PATH:${{ env.CPPCHECK_CACHE_PATH }}/build/bin" + echo "PATH=$PATH" >> "$GITHUB_ENV" + NOCONFIGURE=1 ./autogen.sh mkdir _build cd _build @@ -160,7 +191,7 @@ jobs: - name: Run distcheck run: | cd _build - make -j ${{ env.JOBS }} distcheck DISTCHECK_CONFIGURE_FLAGS="${{ env.CONFIGURE_FLAGS }}"; + make -j ${{ env.JOBS }} distcheck DISTCHECK_CONFIGURE_FLAGS="${{ env.CONFIGURE_FLAGS }} --disable-cppcheck"; - name: ccache statistics if: ${{ env.DEBUG == '1' }} diff --git a/addons/src/ao_tasks.c b/addons/src/ao_tasks.c index 0cee91ec9..9f5729976 100644 --- a/addons/src/ao_tasks.c +++ b/addons/src/ao_tasks.c @@ -636,18 +636,21 @@ static void free_update_tasks_for_doc_arguments(gpointer data) static void update_tasks_for_doc(AoTasks *t, GeanyDocument *doc, gboolean clear) { - AoTasksUpdateTasksForDocArguments *arguments = g_slice_alloc(sizeof *arguments); - arguments->t = t; - arguments->doc = doc; - arguments->clear = clear; + AoTasksUpdateTasksForDocArguments *arguments; if (!DOC_VALID(doc)) return; + arguments = g_slice_alloc(sizeof *arguments); + arguments->t = t; + arguments->doc = doc; + arguments->clear = clear; + /* Check for task tokens in an idle callback to wait until Geany applied Scintilla highlighting * styles as we need them to be set before checking for tasks. */ g_idle_add_full(G_PRIORITY_LOW, update_tasks_for_doc_idle_cb, arguments, free_update_tasks_for_doc_arguments); + /* cppcheck-suppress memleak symbolName=arguments */ } diff --git a/build/cppcheck-geany-plugins.cfg b/build/cppcheck-geany-plugins.cfg index 88fbe8ec8..0647ab26c 100644 --- a/build/cppcheck-geany-plugins.cfg +++ b/build/cppcheck-geany-plugins.cfg @@ -1,11 +1,7 @@ - - - - diff --git a/build/cppcheck.mk b/build/cppcheck.mk index e1a5e01e0..8874a1ad2 100644 --- a/build/cppcheck.mk +++ b/build/cppcheck.mk @@ -3,9 +3,15 @@ if HAVE_CPPCHECK check-cppcheck: $(srcdir) $(CPPCHECK) \ + --inline-suppr \ -q --template=gcc --error-exitcode=2 \ + --library=gtk \ --library=$(top_srcdir)/build/cppcheck-geany-plugins.cfg \ -I$(GEANY_INCLUDEDIR)/geany \ + -UGEANY_PRIVATE \ + -DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \ + $(filter -j%,$(MAKEFLAGS)) \ + $(LOCAL_AM_CFLAGS) \ $(AM_CPPCHECKFLAGS) $(CPPCHECKFLAGS) \ $(srcdir) diff --git a/build/markdown.m4 b/build/markdown.m4 index 6c1f53a61..01acc0b6c 100644 --- a/build/markdown.m4 +++ b/build/markdown.m4 @@ -46,16 +46,22 @@ AC_DEFUN([GP_CHECK_MARKDOWN], [markdown_library=libmarkdown]) GP_STATUS_FEATURE_ADD([Markdown library], [$markdown_library]) - GTK_VERSION=2.16 - WEBKIT_VERSION=1.1.13 + GTK_VERSION=3.0 + WEBKIT_VERSION=2.30 + + dnl Support both webkit2gtk 4.0 and 4.1, as the only difference is the + dnl libsoup version in the API, which we don't use. + dnl Prefer the 4.1 version, but use the 4.0 version as fallback if + dnl available -- yet still ask for the 4.1 if neither are available + webkit_package=webkit2gtk-4.1 + PKG_CHECK_EXISTS([${webkit_package} >= ${WEBKIT_VERSION}],, + [PKG_CHECK_EXISTS([webkit2gtk-4.0 >= ${WEBKIT_VERSION}], + [webkit_package=webkit2gtk-4.0])]) - GP_CHECK_GTK3([webkit_package=webkit2gtk-4.0], - [webkit_package=webkit-1.0]) GP_CHECK_PLUGIN_DEPS([markdown], [MARKDOWN], [$GP_GTK_PACKAGE >= ${GTK_VERSION} $webkit_package >= ${WEBKIT_VERSION} gthread-2.0]) - AM_CONDITIONAL([MARKDOWN_WEBKIT2], [test "$webkit_package" = webkit2gtk-4.0]) GP_COMMIT_PLUGIN_STATUS([Markdown]) diff --git a/build/webhelper.m4 b/build/webhelper.m4 index eacef95c4..3b7fa2525 100644 --- a/build/webhelper.m4 +++ b/build/webhelper.m4 @@ -2,12 +2,11 @@ AC_DEFUN([GP_CHECK_WEBHELPER], [ GP_ARG_DISABLE([WebHelper], [auto]) - GTK_VERSION=2.16 - dnl 2.22 for glib-mkenums' @basename@ template - GLIB_VERSION=2.22 - GIO_VERSION=2.18 + GTK_VERSION=3.0 + GLIB_VERSION=2.38 + GIO_VERSION=2.30 GDK_PIXBUF_VERSION=2.0 - WEBKIT_VERSION=1.1.18 + WEBKIT_VERSION=2.18 AC_PATH_PROG([GLIB_MKENUMS], [glib-mkenums], [no]) AC_SUBST([GLIB_MKENUMS]) @@ -19,13 +18,22 @@ AC_DEFUN([GP_CHECK_WEBHELPER], fi fi + dnl Support both webkit2gtk 4.0 and 4.1, as the only difference is the + dnl libsoup version in the API, which we don't use. + dnl Prefer the 4.1 version, but use the 4.0 version as fallback if + dnl available -- yet still ask for the 4.1 if neither are available + webkit_package=webkit2gtk-4.1 + PKG_CHECK_EXISTS([${webkit_package} >= ${WEBKIT_VERSION}],, + [PKG_CHECK_EXISTS([webkit2gtk-4.0 >= ${WEBKIT_VERSION}], + [webkit_package=webkit2gtk-4.0])]) + GP_CHECK_PLUGIN_GTK3_ONLY([webhelper]) GP_CHECK_PLUGIN_DEPS([WebHelper], [WEBHELPER], [$GP_GTK_PACKAGE >= ${GTK_VERSION} glib-2.0 >= ${GLIB_VERSION} gio-2.0 >= ${GIO_VERSION} gdk-pixbuf-2.0 >= ${GDK_PIXBUF_VERSION} - webkit2gtk-4.0 >= ${WEBKIT_VERSION} + $webkit_package >= ${WEBKIT_VERSION} gthread-2.0]) diff --git a/codenav/src/goto_file.c b/codenav/src/goto_file.c index 08c4dd41e..1da44ec17 100644 --- a/codenav/src/goto_file.c +++ b/codenav/src/goto_file.c @@ -163,8 +163,11 @@ directory_check(GtkEntry* entry, GtkEntryCompletion* completion) if (old_model != NULL) { /* Restore the no-sub-directory model */ log_debug("Restoring old model!"); + gtk_entry_completion_set_model (completion, old_model); + g_object_unref(old_model); old_model = NULL; + g_free(curr_dir); curr_dir = NULL; } @@ -185,7 +188,10 @@ directory_check(GtkEntry* entry, GtkEntryCompletion* completion) /* Save the completion_mode for future restore. */ if (old_model == NULL) + { old_model = gtk_entry_completion_get_model(completion); + g_object_ref(old_model); + } log_debug("New completion list!"); diff --git a/geanyctags/README b/geanyctags/README index f9b563a41..ad91b862d 100644 --- a/geanyctags/README +++ b/geanyctags/README @@ -9,9 +9,11 @@ About GeanyCtags adds a simple support for generating and querying ctags files for a Geany project. It requires that the ctags command is installed in a system path. On -unix systems, distributions usually provide the ctags package; on Windows, the -ctags binary can be found in the zip Windows distribution from the ctags home -page (http://ctags.sourceforge.net). +unix systems, distributions usually provide the ctags (original but orphaned +and unmaintained) or universal-ctags (forked and maintained) packages. On Windows, +the universal-ctags binaries can be downloaded from:: + + https://github.com/universal-ctags/ctags-win32/releases Even though Geany supports symbol definition searching by itself within the open files (and with a plugin support within the whole project), tag regeneration can become @@ -97,7 +99,7 @@ Downloads GeanyCtags is part of the combined Geany Plugins release. For more information and downloads, please visit -http://plugins.geany.org/geany-plugins/ +https://plugins.geany.org/geany-plugins/ Development Code ================ @@ -109,9 +111,10 @@ Get the code from:: Ideas, questions, patches and bug reports ========================================= -Please direct all questions, bug reports and patches to the plugin author using the -email address listed below or to the Geany mailing list to get some help from other -Geany users. +Please direct all questions, bug reports and patches to the combined geany-plugins +project at https://github.com/geany/geany-plugins and open the corresponding +bug report or pull request there. To notify the author of this plugin about +your post, mention him using his github user name (@techee). 2010-2014 by Jiří Techet techet(at)gmail(dot)com diff --git a/geanyctags/src/geanyctags.c b/geanyctags/src/geanyctags.c index 00a5c71ab..6e5ed8428 100644 --- a/geanyctags/src/geanyctags.c +++ b/geanyctags/src/geanyctags.c @@ -162,6 +162,8 @@ static void spawn_cmd(const gchar *cmd, const gchar *dir) msgwin_msg_add(COLOR_BLACK, -1, NULL, "%s", out); } + /* cppcheck-suppress mismatchAllocDealloc symbolName=argv + * argv is built manually, but is a valid GStrv */ g_strfreev(argv); g_free(working_dir); g_free(out); @@ -395,6 +397,10 @@ static gboolean find_next(tagFile *tf, tagEntry *entry, MatchType match_type) return ret; } +#if ! GLIB_CHECK_VERSION(2, 70, 0) +# define g_pattern_spec_match_string g_pattern_match_string +#endif + static gboolean filter_tag(tagEntry *entry, GPatternSpec *name, gboolean declaration, gboolean case_sensitive) { gboolean filter = TRUE; @@ -415,7 +421,7 @@ static gboolean filter_tag(tagEntry *entry, GPatternSpec *name, gboolean declara else entry_name = g_utf8_strdown(entry->name, -1); - filter = !g_pattern_match_string(name, entry_name); + filter = !g_pattern_spec_match_string(name, entry_name); g_free(entry_name); diff --git a/geanygendoc/data/filetypes/c.conf b/geanygendoc/data/filetypes/c.conf index 506d73da7..1159b15ae 100644 --- a/geanygendoc/data/filetypes/c.conf +++ b/geanygendoc/data/filetypes/c.conf @@ -41,6 +41,8 @@ doctypes = { struct.prototype.policy = FORWARD; member.policy = FORWARD; enumval.policy = FORWARD; + # usually, locals are just not documented and get in the way + local.policy = FORWARD; function = { template = "/**\n * {symbol}:\n{for arg in argument_list} * @{arg}: {cursor}\n{end} * \n * {cursor}\n{if returns} * \n * Returns: \n{end}{if write_since}{if returns} * \n{end} * Since: \n{end} */\n"; @@ -73,6 +75,9 @@ doctypes = { } doxygen = { + # usually, locals are just not documented and get in the way + local.policy = FORWARD; + function.template = "/**\n * {doxygen_prefix}brief {cursor}\n{for a in argument_list} * {doxygen_prefix}param {a} \n{end}{if returns} * {doxygen_prefix}returns \n{end}{if write_since} * {doxygen_prefix}since \n{end} * \n * \n */\n"; macro.template = "/**\n * {doxygen_prefix}brief {cursor}\n{for a in argument_list} * {doxygen_prefix}param {a} \n{end}{if returns} * {doxygen_prefix}returns \n{end}{if write_since} * {doxygen_prefix}since \n{end} * \n * \n */\n"; struct.member = { diff --git a/geanygendoc/docs/manual.rst b/geanygendoc/docs/manual.rst index 8c492d842..10f4f45e5 100644 --- a/geanygendoc/docs/manual.rst +++ b/geanygendoc/docs/manual.rst @@ -348,6 +348,8 @@ Known types A function. ``interface`` An interface. +``local`` + A local variable. ``member`` A member (of a structure for example). ``method`` diff --git a/geanygendoc/src/ggd-options.c b/geanygendoc/src/ggd-options.c index 123721feb..e691b7678 100644 --- a/geanygendoc/src/ggd-options.c +++ b/geanygendoc/src/ggd-options.c @@ -202,6 +202,7 @@ ggd_opt_group_add_entry (GgdOptGroup *group, g_array_append_val (group->prefs, entry); + /* cppcheck-suppress memleak symbolName=entry.key */ return &g_array_index (group->prefs, GgdOptEntry, group->prefs->len -1); } diff --git a/geanygendoc/src/ggd-tag-utils.c b/geanygendoc/src/ggd-tag-utils.c index a5a3b0425..1d1fff800 100644 --- a/geanygendoc/src/ggd-tag-utils.c +++ b/geanygendoc/src/ggd-tag-utils.c @@ -255,6 +255,7 @@ static const struct { { tm_tag_field_t, "field" }, { tm_tag_function_t, "function" }, { tm_tag_interface_t, "interface" }, + { tm_tag_local_var_t, "local" }, { tm_tag_member_t, "member" }, { tm_tag_method_t, "method" }, { tm_tag_namespace_t, "namespace" }, diff --git a/geanygendoc/src/ggd.c b/geanygendoc/src/ggd.c index b60d9d79b..bc55a300f 100644 --- a/geanygendoc/src/ggd.c +++ b/geanygendoc/src/ggd.c @@ -208,7 +208,7 @@ get_env_for_tag (GgdFileType *ft, CtplValue *v; GList *tmp = children; - if (el->type & setting->matches) { + if (type_name && el->type & setting->matches) { v = g_hash_table_lookup (vars, type_name); if (! v) { v = ctpl_value_new_array (CTPL_VTYPE_STRING, 0, NULL); diff --git a/geanymacro/ABOUT b/geanymacro/ABOUT deleted file mode 100644 index 5cb829a02..000000000 --- a/geanymacro/ABOUT +++ /dev/null @@ -1,44 +0,0 @@ -geanymacro is a plugin to provide user defined macros for Geany. It started out -as part of the ConText feature parity plugin, which was split into individual -plugins to better suit Geany's ethos of being as light as possible while -allowing users to select which features they want to add to the core editor. -The idea was taken from a Text Editor for Windows called ConText. - -This plugin allows you to record and use your own macros. Macros are sequences -of actions that can then be repeated with a single key combination. So if you -had dozens of lines where you wanted to delete the last 2 characters, you could -simple start recording, press End, Backspace, Backspace, down line and then -stop recording. Then simply trigger the macro and it would automatically edit -the line and move to the next. You could then just repeatedly trigger the macro -to do as many lines as you want. - -Select Record Macro from the Tools menu and you will be prompted with a dialog -box. You need to specify a key combination that isn't being used, and a name -for the macro to help you identify it. Then press Record. What you do in the -editor is then recorded until you select Stop Recording Macro from the Tools -menu. Simply pressing the specified key combination will re-run the macro. - -To edit the macros you already have, select Edit Macro from the Tools menu. You -can select a macro and delete it, or re-record it. Selecting the edit option -allows you to view all the individual elements that make up the macro. You can -select a diferent command for each element, move them, add new elements, delete -elements, or if it's replace/insert, you can edit the text that replaces the -selected text, or is inserted. You can also click on a macro's name and change -it, or the key combination and re-define that assuming that the new name or key -combination are not already in use. - -The only thing to bear in mind is that undo and redo actions are not recorded, -and won't be replayed when the macro is re-run. - -You can alter the default behaviour of this plugin by selecting Plugin Manager -under the Tools menu, selecting this plugin, and cliking Preferences. -You can change: - -Save Macros when close Geany - If this is selected then Geany will save any - recorded macros and reload them for use the next time you open Geany, if - not they will be lost when Geany is closed. -Ask before replaceing existing Macros - If this is selected then if you try - recording a macro over an existing one it will check before over-writing - it, giving you the option of trying a different name or key trigger - combination, otherwise it will simply erase any existing macros with the - same name, or the same key trigger combination. \ No newline at end of file diff --git a/geanynumberedbookmarks/ABOUT b/geanynumberedbookmarks/ABOUT deleted file mode 100644 index 029643ffb..000000000 --- a/geanynumberedbookmarks/ABOUT +++ /dev/null @@ -1,62 +0,0 @@ -geanynumberedbookmarks is a plugin to provide users with 10 numbered bookmarks -(in addition to the usual bookkmarks). It started out as part of the ConText -feature parity plugin, which was split into individual plugins to better suit -Geany's ethos of being as light as possible while allowing users to select -which features they want to add to the core editor. The idea was taken from a -Text Editor for Windows called ConText. - -Normaly if you had more than one bookmark, you would have to cycle through them -until you reached the one you wanted. With this plugin you can go straight to -the bookmark that you want with a single key combination. - -To set a numbered bookmark press Ctrl+Shift+(a number from 0 to 9). You will -see a marker apear next to the line number. If you press Ctrl+Shift+(a number) -on a line that already has that bookmark number then it removes the bookmark, -otherwise it will move the bookmark there if it was set on a different line, -or create it if it had not already been set. To move to a previously set -bookmark press Ctrl+(bookmark number). You can also specify when in the -bookmarked line the cursor is moved to when you move to a previously set -bookmark. You can choose to move to the start of the line, the end of the line, -how far into the line the cursor was when the bookmark was set, or try and keep -the cursor in the column that you are in at the moment (line length allowing). -Only the most recently set bookmark on a line will be shown, but you can have -more than one bookmark per line. This plugin does not interfer with regular -bookmarks. When a file is saved, Geany will remember the numbered bookmarks and -make sure that they are set the next time you open the file. - -This plugin also will remember the state of folds in a file (open or not) if -you want it to and re-apply this the next time you open the file. - -This plugin will also remember standard non-numbered bookmarks and restore -these when a file is next reloaded if you want it to. - -You can alter the default behaviour of this plugin by selecting Plugin Manager -under the Tools menu, selecting this plugin, and cliking Preferences. -You can change: -Remember fold state - if this is set then this plugin will remember the state - of any folds along with the numbered bookmarks and set them when the file - is next loaded. -Center view when goto bookmark - If this is set it will try to make sure that - the numbered bookmark that you are going to is in the center of the screen, - otherwise it will simply be on the screen somewhere. -Move to... - This allows you to choose where in the bookmarked line the cursor - is placed when you move to a bookmarked line. -Save file settings... - This allows you the option of saving the settings of a - file (the numbered bookmark positions, folding states, and standard - bookmark positions) in either the central settings file for geany plugins, - or to a file with the same name but a suffix (by default this is ".gnbs.conf") - in the same directory as the file. This allows the user the ability to - synchronise the settings for a file along with the file itself across more - than one computer. The default suffix can be changed by editing the - numbered bookmarks pluggin settings file. This will vary from OS to OS but - will always be "settings.conf" in a directory called - "Geany_Numbered_Bookmarks". On my OS it's - ".config/geany/plugins/Geany_Numbered_Bookmarks/settings.conf" in my home - directory, but otherwise you'll have to search for it. In the Settings - section of the file near the top will be a line - "File_Details_Suffix=.gnbs.conf". Simply change this to whatever you would - prefer (if geany is running while you edit this file it may over-write your - new suffix so best close geany before editing this file). -Remember normal Bookmarks - If this is set then the plugin will remember - standard non-numbered bookmarks, and restore them when the file is next - loaded. diff --git a/geanyprj/src/Makefile.am b/geanyprj/src/Makefile.am index ef9e8df6c..8b921681e 100644 --- a/geanyprj/src/Makefile.am +++ b/geanyprj/src/Makefile.am @@ -23,7 +23,4 @@ unittests_CFLAGS = $(GEANY_CFLAGS) -DUNITTESTS unittests_LDADD = @GEANY_LIBS@ $(INTLLIBS) @CHECK_LIBS@ endif -AM_CPPCHECKFLAGS = --suppress='constStatement:*' -AM_CPPCHECKFLAGS += --suppress='memleak:utils.c:72' - include $(top_srcdir)/build/cppcheck.mk diff --git a/geanyprj/src/utils.c b/geanyprj/src/utils.c index 281e87cc4..f8a3e6d8d 100644 --- a/geanyprj/src/utils.c +++ b/geanyprj/src/utils.c @@ -69,7 +69,10 @@ gchar *normpath(const gchar *filename) return g_strdup("."); v = g_strsplit_set(filename, "/\\", -1); if (!g_strv_length(v)) + { + g_strfreev(v); return g_strdup("."); + } out = g_malloc0(sizeof(gchar *) * (g_strv_length(v) + 2)); pout = out; diff --git a/geniuspaste/src/geniuspaste.c b/geniuspaste/src/geniuspaste.c index 1815905c5..27035bd01 100644 --- a/geniuspaste/src/geniuspaste.c +++ b/geniuspaste/src/geniuspaste.c @@ -381,6 +381,8 @@ static gchar *pastebin_get_language(const Pastebin *pastebin, gchar *lang = g_key_file_get_string(pastebin->config, PASTEBIN_GROUP_LANGUAGES, geany_ft_name, NULL); + /* cppcheck-suppress memleak symbolName=lang + * obvious cppcheck bug */ return lang ? lang : pastebin_get_default(pastebin, "language", ""); } @@ -750,6 +752,9 @@ static void show_msgbox(GtkMessageType type, GtkButtonsType buttons, /* run the dialog */ gtk_dialog_run(GTK_DIALOG(dlg)); gtk_widget_destroy(dlg); + + g_free(markup); + /* cppcheck-suppress memleak symbolName=dlg */ } static void debug_log_message_body(SoupMessage *msg, diff --git a/git-changebar/src/gcb-plugin.c b/git-changebar/src/gcb-plugin.c index b6f8ad5c3..dd054e44e 100644 --- a/git-changebar/src/gcb-plugin.c +++ b/git-changebar/src/gcb-plugin.c @@ -566,6 +566,7 @@ get_cached_blob_contents_async (const gchar *path, } g_async_queue_push (G_queue, job); + /* cppcheck-suppress memleak symbolName=job */ } } diff --git a/latex/ABOUT b/latex/ABOUT deleted file mode 100644 index 8184b962f..000000000 --- a/latex/ABOUT +++ /dev/null @@ -1,17 +0,0 @@ -LaTeX is a little plugin to improve support of LaTeX on Geany. -It implements a couple of maybe useful functions: - - * Wizard to create new LaTeX documents in a fast and easy way - with a bunch of templates available - * A front end for add labels \label{} and references \ref{} and - \pageref{} with getting suggestion from aux file of document - * Inserting special characters through menu - * Help entering the right fields for BibTeX entries by - providing templates - * Easy inserting format patterns like \texttt{} through menu - * Support on inserting environments by offering an dialog and - recognising selections - * Shortcuts for inserting \item and \newline - * Toolbar with often used format options - -You will find more information inside documentation. diff --git a/latex/README b/latex/README index 025af660f..701fc2536 100644 --- a/latex/README +++ b/latex/README @@ -1,4 +1,29 @@ -Documentation has been moved into doc subfolder. There you you should -find a PDF or HTML file shipped with sources of this plugin. If there -is no documentation available there, please check -https://plugins.geany.org/latex.html instead. +About +----- + +This plugin improves support of LaTeX on Geany. + +Features +-------- + +Some useful functions are provided: + +* Wizard to create new LaTeX documents in a fast and easy way + with a bunch of templates available + +* A front end for add labels ``\label{}`` and references ``\ref{}`` and + ``\pageref{}`` with getting suggestion from aux file of document + +* Inserting special characters through menu + +* Help entering the right fields for BibTeX entries by + providing templates + +* Easy inserting format patterns like ``\texttt{}`` through menu + +* Support on inserting environments by offering an dialog and + recognising selections + +* Shortcuts for inserting ``\item`` and ``\newline`` + +* Toolbar with often used format options diff --git a/latex/src/latexenvironments.c b/latex/src/latexenvironments.c index 02fedc3f2..6381db2cb 100644 --- a/latex/src/latexenvironments.c +++ b/latex/src/latexenvironments.c @@ -1,7 +1,7 @@ /* * latexenvironments.c * - * Copyright 2009-2012 Frank Lanitz + * Copyright 2009-2024 Frank Lanitz * * 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 @@ -69,6 +69,7 @@ void glatex_insert_environment(const gchar *environment, gint type) /* Only do anything if it is realy needed to */ if (doc != NULL && environment != NULL) { + /* Checking whether we do have a selection */ if (sci_has_selection(doc->editor->sci)) { gchar *selection = NULL; @@ -92,12 +93,9 @@ void glatex_insert_environment(const gchar *environment, gint type) g_free(replacement); } - else + else /* No selection found*/ { - gint indent, pos; - GString *tmpstring = NULL; - gchar *tmp = NULL; - static const GeanyIndentPrefs *indention_prefs = NULL; + gchar *tmpstring = NULL; if (type == -1) { @@ -114,49 +112,43 @@ void glatex_insert_environment(const gchar *environment, gint type) } } } - pos = sci_get_current_position(doc->editor->sci); - sci_start_undo_action(doc->editor->sci); - tmpstring = g_string_new("\\begin{"); - g_string_append(tmpstring, environment); - if (utils_str_equal(environment, "block") == TRUE) { - g_string_append(tmpstring, "}{}"); + tmpstring = g_strconcat( + "\\begin{", + environment, + "}{}\n%cursor%\n\\end{", + environment, + "}", + NULL); } - else + else /* We don't have a block-like environment */ { - g_string_append(tmpstring, "}"); - } - g_string_append(tmpstring, "\n"); - - - if (type == GLATEX_ENVIRONMENT_TYPE_LIST) - { - g_string_append(tmpstring, "\t\\item "); - } - - tmp = g_string_free(tmpstring, FALSE); - glatex_insert_string(tmp, TRUE); - g_free(tmp); - - indent = sci_get_line_indentation(doc->editor->sci, - sci_get_line_from_position(doc->editor->sci, pos)); - - tmp = g_strdup_printf("\n\\end{%s}", environment); - glatex_insert_string(tmp, FALSE); - g_free(tmp); - - indention_prefs = editor_get_indent_prefs(doc->editor); - if (type == GLATEX_ENVIRONMENT_TYPE_LIST) - { - sci_set_line_indentation(doc->editor->sci, - sci_get_current_line(doc->editor->sci), - indent + indention_prefs->width); + if (type == GLATEX_ENVIRONMENT_TYPE_LIST) + { + tmpstring = g_strconcat( + "\\begin{", + environment, + "}\n\t\\item %cursor%\n\\end{", + environment, + "}", + NULL); + } + else + { + tmpstring = g_strconcat( + "\\begin{", + environment, + "}\n%cursor%\n\\end{", + environment, + "}", + NULL); + } } - sci_set_line_indentation(doc->editor->sci, - sci_get_current_line(doc->editor->sci) + 1, indent); + glatex_insert_snippet(tmpstring); + g_free(tmpstring); sci_end_undo_action(doc->editor->sci); } } diff --git a/latex/src/latexutils.c b/latex/src/latexutils.c index ebf83f4b1..28d6b0e52 100644 --- a/latex/src/latexutils.c +++ b/latex/src/latexutils.c @@ -89,12 +89,22 @@ void glatex_usepackage(const gchar *pkg, const gchar *options) ui_set_statusbar(TRUE, _("Could not determine where to insert package: %s"), pkg ); } - void glatex_enter_key_pressed_in_entry(G_GNUC_UNUSED GtkWidget *widget, gpointer dialog) { gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); } +void glatex_insert_snippet(const gchar *string) +{ + GeanyDocument *doc = NULL; + + doc = document_get_current(); + if (doc != NULL && string != NULL) + { + gint pos = sci_get_current_position(doc->editor->sci); + editor_insert_snippet(doc->editor, pos, string); + } +} void glatex_insert_string(const gchar *string, gboolean reset_position) @@ -117,7 +127,6 @@ glatex_insert_string(const gchar *string, gboolean reset_position) } } - void glatex_replace_special_character(void) { GeanyDocument *doc = NULL; diff --git a/latex/src/latexutils.h b/latex/src/latexutils.h index cd4b1b307..c5a7c49cf 100644 --- a/latex/src/latexutils.h +++ b/latex/src/latexutils.h @@ -26,6 +26,7 @@ gchar **glatex_read_file_in_array(const gchar *filename); void glatex_usepackage(const gchar *pkg, const gchar *options); void glatex_enter_key_pressed_in_entry(G_GNUC_UNUSED GtkWidget *widget, gpointer dialog); +void glatex_insert_snippet(const gchar *string); void glatex_insert_string(const gchar *string, gboolean reset_position); void glatex_replace_special_character(void); diff --git a/lineoperations/src/lo_prefs.c b/lineoperations/src/lo_prefs.c index a99803215..3363ce740 100644 --- a/lineoperations/src/lo_prefs.c +++ b/lineoperations/src/lo_prefs.c @@ -117,8 +117,6 @@ lo_init_prefs(GeanyPlugin *plugin) lo_info->use_collation_compare = utils_get_setting_boolean(config, "general", "use_collation_compare", FALSE); - printf("VALUE: %d\n", lo_info->use_collation_compare); - g_key_file_free(config); } @@ -128,4 +126,4 @@ void lo_free_info() { g_free(lo_info->config_file); g_free(lo_info); -} \ No newline at end of file +} diff --git a/markdown/README b/markdown/README index 65f1b845a..b5f28f854 100644 --- a/markdown/README +++ b/markdown/README @@ -146,8 +146,8 @@ Requirements The plugin depends on the following libraries: -* `GTK+ `_ 2.16 or greater -* `WebKitGTK+ `_ 1.1.18 or greater +* `GTK+ `_ 3.0 or greater +* `WebKitGTK+ `_ API 4.0 or 4.1 License ------- diff --git a/markdown/src/Makefile.am b/markdown/src/Makefile.am index 285ea00c5..91f80a70f 100644 --- a/markdown/src/Makefile.am +++ b/markdown/src/Makefile.am @@ -35,8 +35,4 @@ markdown_la_CFLAGS += $(LIBMARKDOWN_CFLAGS) markdown_la_LIBADD += $(LIBMARKDOWN_LIBS) endif -if MARKDOWN_WEBKIT2 -markdown_la_CFLAGS += -DMARKDOWN_WEBKIT2 -endif - include $(top_srcdir)/build/cppcheck.mk diff --git a/markdown/src/conf.c b/markdown/src/conf.c index d54cc9a6b..ad338e15e 100644 --- a/markdown/src/conf.c +++ b/markdown/src/conf.c @@ -233,7 +233,7 @@ markdown_config_get_string_key(MarkdownConfig *conf, const gchar *group, GError *error = NULL; out_str = g_key_file_get_string(conf->priv->kf, group, key, &error); - if (error) { + if (!out_str) { g_debug("Config read failed: %s", error->message); g_error_free(error); error = NULL; out_str = g_strdup(default_value); @@ -451,7 +451,7 @@ markdown_config_save(MarkdownConfig *conf) /*g_debug("Saving: %s\n%s", conf->priv->filename, contents);*/ - if (error) { + if (!contents) { g_warning("Error getting config data as string: %s", error->message); g_error_free(error); error = NULL; return success; diff --git a/markdown/src/viewer.c b/markdown/src/viewer.c index b9ab58f70..a8a8605a0 100644 --- a/markdown/src/viewer.c +++ b/markdown/src/viewer.c @@ -22,11 +22,7 @@ #include "config.h" #include #include -#ifdef MARKDOWN_WEBKIT2 -# include -#else -# include -#endif +#include #include #ifndef FULL_PRICE # include @@ -194,12 +190,15 @@ replace_all(MarkdownViewer *self, { gchar *ptr; gsize needle_len = strlen(needle); + gsize replacement_len = strlen(replacement); + goffset offset = 0; /* For each occurrence of needle in haystack */ - while ((ptr = strstr(haystack->str, needle)) != NULL) { - goffset offset = ptr - haystack->str; + while ((ptr = strstr(haystack->str + offset, needle)) != NULL) { + offset = ptr - haystack->str; g_string_erase(haystack, offset, needle_len); g_string_insert(haystack, offset, replacement); + offset += replacement_len; } } @@ -300,7 +299,6 @@ pop_scroll_pos(MarkdownViewer *self) return popped; } -#ifdef MARKDOWN_WEBKIT2 static void on_webview_load_changed(MarkdownViewer *self, WebKitLoadEvent load_event, @@ -311,21 +309,6 @@ on_webview_load_changed(MarkdownViewer *self, pop_scroll_pos(self); } } -#else -static void -on_webview_load_status_notify(WebKitWebView *view, GParamSpec *pspec, - MarkdownViewer *self) -{ - WebKitLoadStatus load_status; - - g_object_get(view, "load-status", &load_status, NULL); - - /* When the webkit is done loading, reset the scroll position. */ - if (load_status == WEBKIT_LOAD_FINISHED) { - pop_scroll_pos(self); - } -} -#endif gchar * markdown_viewer_get_html(MarkdownViewer *self) @@ -405,23 +388,12 @@ markdown_viewer_update_view(MarkdownViewer *self) /* Connect a signal handler (only needed once) to restore the scroll * position once the webview is reloaded. */ if (self->priv->load_handle == 0) { -#ifdef MARKDOWN_WEBKIT2 self->priv->load_handle = g_signal_connect_swapped(WEBKIT_WEB_VIEW(self), "load-changed", G_CALLBACK(on_webview_load_changed), self); -#else - self->priv->load_handle = - g_signal_connect_swapped(WEBKIT_WEB_VIEW(self), "notify::load-status", - G_CALLBACK(on_webview_load_status_notify), self); -#endif } -#ifdef MARKDOWN_WEBKIT2 webkit_web_view_load_html(WEBKIT_WEB_VIEW(self), html, base_uri); -#else - webkit_web_view_load_string(WEBKIT_WEB_VIEW(self), html, "text/html", - self->priv->enc, base_uri); -#endif g_free(base_uri); g_free(html); diff --git a/markdown/src/viewer.h b/markdown/src/viewer.h index f69f616e0..b18192bea 100644 --- a/markdown/src/viewer.h +++ b/markdown/src/viewer.h @@ -23,11 +23,7 @@ #define MARKDOWN_VIEWER_H 1 #include -#ifdef MARKDOWN_WEBKIT2 -# include -#else -# include -#endif +#include G_BEGIN_DECLS diff --git a/projectorganizer/README b/projectorganizer/README index 11329819f..8bf73e10b 100644 --- a/projectorganizer/README +++ b/projectorganizer/README @@ -216,7 +216,7 @@ Downloads Project Organizer is part of the combined Geany Plugins release. For more information and downloads, please visit -http://plugins.geany.org/geany-plugins/ +https://plugins.geany.org/geany-plugins/ Development Code ================ @@ -228,9 +228,10 @@ Get the code from:: Ideas, questions, patches and bug reports ========================================= -Please direct all questions, bug reports and patches to the plugin author using the -email address listed below or to the Geany mailing list to get some help from other -Geany users. +Please direct all questions, bug reports and patches to the combined geany-plugins +project at https://github.com/geany/geany-plugins and open the corresponding +bug report or pull request there. To notify the author of this plugin about +your post, mention him using his github user name (@techee). 2010-2014 by Jiří Techet techet(at)gmail(dot)com diff --git a/projectorganizer/src/prjorg-main.c b/projectorganizer/src/prjorg-main.c index da98920ef..9af535670 100644 --- a/projectorganizer/src/prjorg-main.c +++ b/projectorganizer/src/prjorg-main.c @@ -223,5 +223,5 @@ void plugin_cleanup(void) void plugin_help (void) { - utils_open_browser("http://plugins.geany.org/projectorganizer.html"); + utils_open_browser("https://plugins.geany.org/projectorganizer.html"); } diff --git a/projectorganizer/src/prjorg-project.c b/projectorganizer/src/prjorg-project.c index 2161925bd..537c8a8cf 100644 --- a/projectorganizer/src/prjorg-project.c +++ b/projectorganizer/src/prjorg-project.c @@ -216,7 +216,7 @@ static gboolean match_basename(gconstpointer pft, gconstpointer user_data) { GPatternSpec *pattern = g_pattern_spec_new(ft->pattern[j]); - if (g_pattern_match_string(pattern, utf8_base_filename)) + if (g_pattern_spec_match_string(pattern, utf8_base_filename)) { ret = TRUE; g_pattern_spec_free(pattern); diff --git a/projectorganizer/src/prjorg-sidebar.c b/projectorganizer/src/prjorg-sidebar.c index 43b48fcbe..0a3e25eef 100644 --- a/projectorganizer/src/prjorg-sidebar.c +++ b/projectorganizer/src/prjorg-sidebar.c @@ -657,7 +657,7 @@ static void find_file_recursive(GtkTreeIter *iter, gboolean case_sensitive, gboo if (!case_sensitive) SETPTR(utf8_name, g_utf8_strdown(utf8_name, -1)); - if (g_pattern_match_string(pattern, utf8_name)) + if (g_pattern_spec_match_string(pattern, utf8_name)) { gchar *utf8_base_path = get_project_base_path(); gchar *utf8_path, *rel_path; @@ -840,7 +840,7 @@ static gboolean match(TMTag *tag, const gchar *name, gboolean declaration, gbool matches = g_strcmp0(name_case, name) == 0; break; case MATCH_PATTERN: - matches = g_pattern_match_string(pspec, name_case); + matches = g_pattern_spec_match_string(pspec, name_case); break; case MATCH_PREFIX: matches = g_str_has_prefix(name_case, name); diff --git a/projectorganizer/src/prjorg-utils.c b/projectorganizer/src/prjorg-utils.c index 2a8847e0d..0b573e5f8 100644 --- a/projectorganizer/src/prjorg-utils.c +++ b/projectorganizer/src/prjorg-utils.c @@ -80,7 +80,7 @@ gboolean patterns_match(GSList *patterns, const gchar *str) foreach_slist (elem, patterns) { GPatternSpec *pattern = elem->data; - if (g_pattern_match_string(pattern, str)) + if (g_pattern_spec_match_string(pattern, str)) return TRUE; } return FALSE; @@ -269,7 +269,7 @@ gchar *try_find_header_source(gchar *utf8_file_name, gboolean is_header, GSList full_name = elem->data; gchar *base_name = g_path_get_basename(full_name); - if (g_pattern_match_string(pattern, base_name)) + if (g_pattern_spec_match_string(pattern, base_name)) { if ((is_header && patterns_match(source_patterns, base_name)) || (!is_header && patterns_match(header_patterns, base_name))) diff --git a/projectorganizer/src/prjorg-utils.h b/projectorganizer/src/prjorg-utils.h index b753a84f0..25c0d28a6 100644 --- a/projectorganizer/src/prjorg-utils.h +++ b/projectorganizer/src/prjorg-utils.h @@ -22,6 +22,10 @@ #include #include +#if ! GLIB_CHECK_VERSION(2, 70, 0) +# define g_pattern_spec_match_string g_pattern_match_string +#endif + gchar *get_relative_path(const gchar *utf8_parent, const gchar *utf8_descendant); gboolean patterns_match(GSList *patterns, const gchar *str); diff --git a/scope/src/Makefile.am b/scope/src/Makefile.am index c161b8ef7..b3398bc38 100644 --- a/scope/src/Makefile.am +++ b/scope/src/Makefile.am @@ -60,8 +60,6 @@ scope_la_CFLAGS = $(AM_CFLAGS) $(VTE_CFLAGS) \ -Wno-shadow \ -I$(top_srcdir)/utils/src -AM_CPPCHECKFLAGS = -DGETTEXT_PACKAGE="geany-plugins" - include $(top_srcdir)/build/cppcheck.mk if UNITTESTS diff --git a/scope/src/debug.c b/scope/src/debug.c index 6974078e7..769bba942 100644 --- a/scope/src/debug.c +++ b/scope/src/debug.c @@ -207,6 +207,8 @@ static void create_send_source(void) g_source_set_callback(send_source, (GSourceFunc) send_commands_cb, NULL, send_source_destroy_cb); send_source_id = g_source_attach(send_source, NULL); + /* cppcheck-suppress memleak symbolName=send_source + * the source is attached and managed through its ID */ } #define HAS_SPAWN_LEAVE_STDIN_OPEN 0 @@ -347,6 +349,8 @@ static void gdb_finalize(void) if (send_channel) { g_io_channel_shutdown(send_channel, FALSE, NULL); + /* cppcheck-suppress doubleFree symbolName=send_channel + * erroneously thinks g_io_channel_shutdown() frees the channel */ g_io_channel_unref(send_channel); send_channel = NULL; diff --git a/treebrowser/src/Makefile.am b/treebrowser/src/Makefile.am index d5bd178f1..147275e93 100644 --- a/treebrowser/src/Makefile.am +++ b/treebrowser/src/Makefile.am @@ -10,7 +10,4 @@ treebrowser_la_CFLAGS = $(AM_CFLAGS) $(GIO_CFLAGS) \ treebrowser_la_LIBADD = $(COMMONLIBS) $(GIO_LIBS) \ $(top_builddir)/utils/src/libgeanypluginutils.la -AM_CPPCHECKFLAGS = --suppress='deallocDealloc:$(srcdir)/treebrowser.c' -AM_CPPCHECKFLAGS += --suppress='doubleFree:$(srcdir)/treebrowser.c' - include $(top_srcdir)/build/cppcheck.mk diff --git a/treebrowser/src/treebrowser.c b/treebrowser/src/treebrowser.c index 0fc8e0191..5441cd047 100644 --- a/treebrowser/src/treebrowser.c +++ b/treebrowser/src/treebrowser.c @@ -1121,6 +1121,7 @@ on_menu_create_new_object(GtkMenuItem *menuitem, const gchar *type) } g_free(uri_new); } + /* cppcheck-suppress doubleFree symbolName=uri */ g_free(uri); } @@ -1192,6 +1193,7 @@ on_menu_refresh(GtkMenuItem *menuitem, gpointer *user_data) } } treebrowser_browse(uri, target_iter); + /* cppcheck-suppress doubleFree symbolName=uri */ g_free(uri); } else diff --git a/vimode/README b/vimode/README index 08202a56d..db6008e65 100644 --- a/vimode/README +++ b/vimode/README @@ -106,7 +106,7 @@ This is an incomplete list of known limitations of the plugin: * only the 'g' flag is supported in the substitute command * in search and substitute the regular expressions are based on Scintilla regular expressions which differ from Vim. Check the Scintilla documentation at - http://www.scintilla.org/ScintillaDoc.html#Searching for more details. + https://www.scintilla.org/ScintillaDoc.html#Searching for more details. In addition, \c is also supported to allow case-insensitive search. FAQ @@ -182,8 +182,10 @@ Jiří Techet, . Bug Reports ----------- -To report bugs, please use the Geany-Plugins GitHub page at -https://github.com/geany/geany-plugins/issues +Please direct all questions, bug reports and patches to the combined geany-plugins +project at https://github.com/geany/geany-plugins and open the corresponding +bug report or pull request there. To notify the author of this plugin about +your post, mention him using his github user name (@techee). License ======= @@ -198,7 +200,7 @@ Downloads ========= Vimode is part of the combined Geany Plugins release. For more information and -downloads, please visit http://plugins.geany.org/geany-plugins/ +downloads, please visit https://plugins.geany.org/geany-plugins/ Source Code =========== diff --git a/vimode/src/backends/backend-geany.c b/vimode/src/backends/backend-geany.c index 6e4d4c842..f46d49a64 100644 --- a/vimode/src/backends/backend-geany.c +++ b/vimode/src/backends/backend-geany.c @@ -337,5 +337,5 @@ void plugin_cleanup(void) void plugin_help(void) { - utils_open_browser("http://plugins.geany.org/vimode.html"); + utils_open_browser("https://plugins.geany.org/vimode.html"); } diff --git a/vimode/src/backends/backend-viw.c b/vimode/src/backends/backend-viw.c index b5ab36619..f95544738 100644 --- a/vimode/src/backends/backend-viw.c +++ b/vimode/src/backends/backend-viw.c @@ -90,8 +90,8 @@ static gboolean on_save(gboolean force) { GtkWidget *dialog = gtk_file_chooser_dialog_new ("Save File", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); + "_Cancel", GTK_RESPONSE_CANCEL, + "_Save", GTK_RESPONSE_ACCEPT, NULL); gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) fname = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); diff --git a/vimode/src/cmd-runner.c b/vimode/src/cmd-runner.c index dcf24ff86..05eaf450b 100644 --- a/vimode/src/cmd-runner.c +++ b/vimode/src/cmd-runner.c @@ -714,9 +714,12 @@ static gboolean process_cmd(CmdDef *cmds, CmdContext *ctx, gboolean ins_mode) { if (orig_mode == VI_MODE_COMMAND_SINGLE) vi_set_mode(VI_MODE_INSERT); + ensure_current_line_expanded(ctx->sci); } else if (!consumed && ctx->kpl) { + /* cppcheck-suppress deallocuse symbolName=kpl + * Not sure how cppcheck gets this wrong here, but all seem OK */ g_free(ctx->kpl->data); ctx->kpl = g_slist_delete_link(ctx->kpl, ctx->kpl); } diff --git a/vimode/src/cmds/motion.c b/vimode/src/cmds/motion.c index 4492d98c9..d528d5d5d 100644 --- a/vimode/src/cmds/motion.c +++ b/vimode/src/cmds/motion.c @@ -41,9 +41,39 @@ void cmd_goto_right(CmdContext *c, CmdParams *p) } +static gint doc_line_from_visible_delta(CmdParams *p, gint line, gint delta, gboolean *overflow) +{ + gboolean oflow = FALSE; + gint new_line = line; + gint i = 0; + + while (i < ABS(delta)) + { + gint inc = delta > 0 ? 1 : -1; + gint tmp = new_line + inc; + + if (tmp < 0 || tmp >= p->line_num) + { + oflow = TRUE; + break; + } + new_line = tmp; + + if (SSM(p->sci, SCI_GETLINEVISIBLE, new_line, 0)) + i++; + } + + if (overflow) + *overflow = oflow; + + return new_line; +} + + void cmd_goto_up(CmdContext *c, CmdParams *p) { gint one_above, pos; + gboolean line_underflow; if (p->line == 0) return; @@ -53,8 +83,8 @@ void cmd_goto_up(CmdContext *c, CmdParams *p) * SCI_CHOOSECARETX which we cannot read directly from Scintilla and which * we want to keep - perform jump to previous/following line and add * one final SCI_LINEUP/SCI_LINEDOWN which recovers SCI_CHOOSECARETX for us. */ - one_above = p->line - p->num - 1; - if (one_above >= 0) + one_above = doc_line_from_visible_delta(p, p->line, -p->num - 1, &line_underflow); + if (!line_underflow) { /* Every case except for the first line - go one line above and perform * SCI_LINEDOWN. This ensures that even with wrapping on, we get the @@ -70,7 +100,7 @@ void cmd_goto_up(CmdContext *c, CmdParams *p) * on, we need to repeat SCI_LINEUP to get to the first line of wrapping. * This may lead to visible slow scrolling which is why there's the * fast case above for anything else but the first line. */ - gint one_below = p->line - p->num + 1; + gint one_below = doc_line_from_visible_delta(p, p->line, -p->num + 1, NULL); gint wrap_count; one_below = one_below > 0 ? one_below : 1; @@ -98,15 +128,13 @@ void cmd_goto_up_nonempty(CmdContext *c, CmdParams *p) static void goto_down(CmdParams *p, gint num) { gint one_above, pos; - gint last_line = p->line_num - 1; - if (p->line == last_line) + if (p->line >= p->line_num - 1) return; - /* see cmd_goto_up() for explanation */ - one_above = p->line + num - 1; - one_above = one_above < last_line ? one_above : last_line - 1; + one_above = doc_line_from_visible_delta(p, p->line, p->num - 1, NULL); pos = SSM(p->sci, SCI_GETLINEENDPOSITION, one_above, 0); + SET_POS_NOX(p->sci, pos, FALSE); SSM(p->sci, SCI_LINEDOWN, 0, 0); } @@ -136,7 +164,7 @@ void cmd_goto_down_one_less_nonempty(CmdContext *c, CmdParams *p) void cmd_goto_page_up(CmdContext *c, CmdParams *p) { gint shift = p->line_visible_num * p->num; - gint new_line = get_line_number_rel(p->sci, -shift); + gint new_line = doc_line_from_visible_delta(p, p->line, -shift, NULL); goto_nonempty(p->sci, new_line, TRUE); } @@ -144,7 +172,7 @@ void cmd_goto_page_up(CmdContext *c, CmdParams *p) void cmd_goto_page_down(CmdContext *c, CmdParams *p) { gint shift = p->line_visible_num * p->num; - gint new_line = get_line_number_rel(p->sci, shift); + gint new_line = doc_line_from_visible_delta(p, p->line, shift, NULL); goto_nonempty(p->sci, new_line, TRUE); } @@ -152,7 +180,7 @@ void cmd_goto_page_down(CmdContext *c, CmdParams *p) void cmd_goto_halfpage_up(CmdContext *c, CmdParams *p) { gint shift = p->num_present ? p->num : p->line_visible_num / 2; - gint new_line = get_line_number_rel(p->sci, -shift); + gint new_line = doc_line_from_visible_delta(p, p->line, -shift, NULL); goto_nonempty(p->sci, new_line, TRUE); } @@ -160,7 +188,7 @@ void cmd_goto_halfpage_up(CmdContext *c, CmdParams *p) void cmd_goto_halfpage_down(CmdContext *c, CmdParams *p) { gint shift = p->num_present ? p->num : p->line_visible_num / 2; - gint new_line = get_line_number_rel(p->sci, shift); + gint new_line = doc_line_from_visible_delta(p, p->line, shift, NULL); goto_nonempty(p->sci, new_line, TRUE); } @@ -168,7 +196,8 @@ void cmd_goto_halfpage_down(CmdContext *c, CmdParams *p) void cmd_goto_line(CmdContext *c, CmdParams *p) { gint num = p->num > p->line_num ? p->line_num : p->num; - goto_nonempty(p->sci, num - 1, TRUE); + num = doc_line_from_visible_delta(p, num, -1, NULL); + goto_nonempty(p->sci, num, TRUE); } @@ -177,22 +206,31 @@ void cmd_goto_line_last(CmdContext *c, CmdParams *p) gint num = p->num > p->line_num ? p->line_num : p->num; if (!p->num_present) num = p->line_num; - goto_nonempty(p->sci, num - 1, TRUE); + num = doc_line_from_visible_delta(p, num, -1, NULL); + goto_nonempty(p->sci, num, TRUE); } void cmd_goto_screen_top(CmdContext *c, CmdParams *p) { + gint line; gint top = p->line_visible_first; gint count = p->line_visible_num; - gint line = top + p->num; - goto_nonempty(p->sci, line > top + count ? top + count : line, FALSE); + gint max = doc_line_from_visible_delta(p, top, count, NULL); + gint num = p->num; + + if (!p->num_present) + num = 0; + + line = doc_line_from_visible_delta(p, top, num, NULL); + goto_nonempty(p->sci, line > max ? max : line, FALSE); } void cmd_goto_screen_middle(CmdContext *c, CmdParams *p) { - goto_nonempty(p->sci, p->line_visible_first + p->line_visible_num/2, FALSE); + gint num = doc_line_from_visible_delta(p, p->line_visible_first, p->line_visible_num / 2, NULL); + goto_nonempty(p->sci, num, FALSE); } @@ -200,7 +238,7 @@ void cmd_goto_screen_bottom(CmdContext *c, CmdParams *p) { gint top = p->line_visible_first; gint count = p->line_visible_num; - gint line = top + count - p->num; + gint line = doc_line_from_visible_delta(p, top, count - p->num, NULL); goto_nonempty(p->sci, line < top ? top : line, FALSE); } diff --git a/vimode/src/excmd-runner.c b/vimode/src/excmd-runner.c index 663291813..4cca689df 100644 --- a/vimode/src/excmd-runner.c +++ b/vimode/src/excmd-runner.c @@ -465,6 +465,7 @@ void excmd_perform(CmdContext *ctx, const gchar *cmd) { case ':': perform_simple_ex_cmd(ctx, cmd + 1); + ensure_current_line_expanded(ctx->sci); break; case '/': case '?': @@ -483,6 +484,7 @@ void excmd_perform(CmdContext *ctx, const gchar *cmd) pos = perform_search(ctx->sci, ctx->search_text, ctx->num, FALSE); if (pos >= 0) SET_POS(ctx->sci, pos, TRUE); + ensure_current_line_expanded(ctx->sci); break; } } diff --git a/vimode/src/utils.c b/vimode/src/utils.c index b491a2dc1..2a367a80c 100644 --- a/vimode/src/utils.c +++ b/vimode/src/utils.c @@ -219,3 +219,11 @@ void goto_nonempty(ScintillaObject *sci, gint line, gboolean scroll) pos = NEXT(sci, pos); SET_POS(sci, pos, scroll); } + + +void ensure_current_line_expanded(ScintillaObject *sci) +{ + gint line = GET_CUR_LINE(sci); + if (!SSM(sci, SCI_GETLINEVISIBLE, line, 0)) + SSM(sci, SCI_ENSUREVISIBLE, line, 0); +} diff --git a/vimode/src/utils.h b/vimode/src/utils.h index e2e83d97c..b535cae81 100644 --- a/vimode/src/utils.h +++ b/vimode/src/utils.h @@ -32,5 +32,6 @@ void perform_substitute(ScintillaObject *sci, const gchar *cmd, gint from, gint const gchar *flag_override); gint get_line_number_rel(ScintillaObject *sci, gint shift); +void ensure_current_line_expanded(ScintillaObject *sci); #endif diff --git a/webhelper/README b/webhelper/README index d097eadbe..86d4971ab 100644 --- a/webhelper/README +++ b/webhelper/README @@ -26,9 +26,9 @@ Prominent features Requirements ============ -This plugin requires GTK+ (>= 2.16), GLib (>= 2.16), GIO (>= 2.18), -GdkPixbuf (>= 2.0), WebKitGTK (>= 1.1.18), and obviously Geany (>= 0.20) to -work. If you intend to build it yourself, you will need to get the development +This plugin requires GTK3, GLib (>= 2.38), GIO (>= 2.30), GdkPixbuf, +WebKit2GTK (either API 4.0 or 4.1), and obviously Geany (>= 1.25) to work. +If you intend to build it yourself, you will need to get the development files of these libraries. You can find these packages at http://www.geany.org/, http://www.gtk.org/ and http://www.webkitgtk.org/. @@ -47,6 +47,18 @@ When loaded into Geany, this plugins adds a web view in the message window (the default), the sidebar or in a separate window. You can find most of the features from this view. +The web view displays the URL chosen in the address bar. This can be any valid +URL that would work in a web browser, for example it could be a local web +server like ``http://localhost/test/index.php``, a local file like +``file:///home/user/projects/test/index.html``, or a remote website like +``https://en.wikipedia.org/wiki/``. + +In addition to a rendered preview, the main feature is the inspector. To +inspect the displayed page, either open the inspector using the toolbar item on +the far end of the address bar, or right click on any element of the page and +select *Inspect Element*. For more documentation on the inspector's features, +see https://webkit.org/web-inspector/. + Bookmarks --------- diff --git a/webhelper/src/gwh-browser.c b/webhelper/src/gwh-browser.c index a520d2e3b..1cb3bf369 100644 --- a/webhelper/src/gwh-browser.c +++ b/webhelper/src/gwh-browser.c @@ -31,6 +31,8 @@ #include #include +#include + #include "gwh-utils.h" #include "gwh-settings.h" #include "gwh-keybindings.h" @@ -76,7 +78,7 @@ static const gdouble zoom_in_factor = 1.2; static const gdouble zoom_out_factor = 1.0 / 1.2; -G_DEFINE_TYPE (GwhBrowser, gwh_browser, GTK_TYPE_VBOX) +G_DEFINE_TYPE_WITH_PRIVATE (GwhBrowser, gwh_browser, GTK_TYPE_BOX) static void @@ -225,6 +227,27 @@ on_item_bookmark_toggled (GtkCheckMenuItem *item, } } +static void +item_show_accelerator (GtkWidget *item, + gsize key_id) +{ + GeanyKeyBinding *binding = keybindings_get_item (gwh_keybindings_get_group (), + key_id); + + if (binding->key) { + /* we need an accel group for setting the accelerator, but we can't get + * Geany's. It doesn't matter though, as this is only for showing the + * accelarator, not actually for tiggering the item. */ + GtkAccelGroup *dummy_accel_group = gtk_accel_group_new (); + + gtk_widget_add_accelerator (item, "activate", dummy_accel_group, + binding->key, binding->mods, + GTK_ACCEL_VISIBLE); + g_object_set_data_full (G_OBJECT (item), "dummy_accel_group", + dummy_accel_group, g_object_unref); + } +} + static void on_url_entry_icon_press (GtkEntry *entry, GtkEntryIconPosition icon_pos, @@ -243,12 +266,43 @@ on_url_entry_icon_press (GtkEntry *entry, G_CALLBACK (on_item_bookmark_toggled), self); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); gtk_widget_show (item); + item_show_accelerator (item, GWH_KB_TOGGLE_BOOKMARK); gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, event->button, event->time); } } +static void +on_item_load_current_file_activate (GtkMenuItem *item, + GwhBrowser *self) +{ + gwh_browser_set_uri_from_document (self, document_get_current ()); +} + +static void +on_url_entry_populate_popup (GtkEntry *entry, + GtkWidget *menu, + GwhBrowser *self) +{ + GtkWidget *item; + GeanyDocument *doc = document_get_current (); + + /* separator */ + item = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show (item); + + /* load current file item */ + item = gtk_menu_item_new_with_mnemonic (_("_Load current file")); + gtk_widget_set_sensitive (item, doc && doc->real_path); + g_signal_connect (item, "activate", + G_CALLBACK (on_item_load_current_file_activate), self); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + gtk_widget_show (item); + item_show_accelerator (item, GWH_KB_LOAD_CURRENT_FILE); +} + static gboolean on_entry_completion_match_selected (GtkEntryCompletion *comp, GtkTreeModel *model, @@ -631,8 +685,6 @@ gwh_browser_class_init (GwhBrowserClass *klass) "The browser's toolbar", GTK_TYPE_TOOLBAR, G_PARAM_READABLE)); - - g_type_class_add_private (klass, sizeof (GwhBrowserPrivate)); } /* a GtkEntryCompletionMatchFunc matching anywhere in the haystack */ @@ -751,6 +803,8 @@ create_toolbar (GwhBrowser *self) G_CALLBACK (on_url_entry_activate), self); g_signal_connect (G_OBJECT (self->priv->url_entry), "icon-press", G_CALLBACK (on_url_entry_icon_press), self); + g_signal_connect (G_OBJECT (self->priv->url_entry), "populate-popup", + G_CALLBACK (on_url_entry_populate_popup), self); g_signal_connect (G_OBJECT (self->priv->url_combo), "notify::active", G_CALLBACK (on_url_combo_active_notify), self); g_signal_connect (G_OBJECT (comp), "match-selected", @@ -837,8 +891,9 @@ gwh_browser_init (GwhBrowser *self) WebKitWebContext *wkcontext; gboolean inspector_detached; - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GWH_TYPE_BROWSER, - GwhBrowserPrivate); + self->priv = gwh_browser_get_instance_private (self); + + gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_VERTICAL); self->priv->default_icon = NULL; /* web view need to be created first because we use it in create_toolbar() */ @@ -950,6 +1005,23 @@ gwh_browser_set_uri (GwhBrowser *self, g_free (real_uri); } +gboolean +gwh_browser_set_uri_from_document (GwhBrowser *self, + GeanyDocument *doc) +{ + gchar *uri; + + /* document must exist on disk */ + if (! doc || ! doc->real_path) + return FALSE; + + uri = g_strconcat ("file://", doc->file_name, NULL); + gwh_browser_set_uri (self, uri); + g_free (uri); + + return TRUE; +} + const gchar * gwh_browser_get_uri (GwhBrowser *self) { diff --git a/webhelper/src/gwh-browser.h b/webhelper/src/gwh-browser.h index faa12e9b8..8432d5a35 100644 --- a/webhelper/src/gwh-browser.h +++ b/webhelper/src/gwh-browser.h @@ -24,6 +24,8 @@ #include #include +#include + G_BEGIN_DECLS @@ -69,6 +71,9 @@ G_GNUC_INTERNAL void gwh_browser_set_uri (GwhBrowser *self, const gchar *uri); G_GNUC_INTERNAL +gboolean gwh_browser_set_uri_from_document (GwhBrowser *self, + GeanyDocument *doc); +G_GNUC_INTERNAL const gchar *gwh_browser_get_uri (GwhBrowser *self); G_GNUC_INTERNAL GtkToolbar *gwh_browser_get_toolbar (GwhBrowser *self); diff --git a/webhelper/src/gwh-keybindings.h b/webhelper/src/gwh-keybindings.h index b768776d2..39431a30b 100644 --- a/webhelper/src/gwh-keybindings.h +++ b/webhelper/src/gwh-keybindings.h @@ -33,6 +33,7 @@ enum { GWH_KB_TOGGLE_INSPECTOR, GWH_KB_SHOW_HIDE_SEPARATE_WINDOW, GWH_KB_TOGGLE_BOOKMARK, + GWH_KB_LOAD_CURRENT_FILE, GWH_KB_COUNT }; diff --git a/webhelper/src/gwh-plugin.c b/webhelper/src/gwh-plugin.c index 68bba3fa2..6480858b3 100644 --- a/webhelper/src/gwh-plugin.c +++ b/webhelper/src/gwh-plugin.c @@ -300,6 +300,13 @@ on_kb_toggle_bookmark (guint key_id) } } +static void +on_kb_load_current_file (guint key_id) +{ + gwh_browser_set_uri_from_document (GWH_BROWSER (G_browser), + document_get_current ()); +} + static gchar * get_config_filename (void) @@ -417,11 +424,6 @@ plugin_init (GeanyData *data) * (g_quark_from_static_string() for example) so it's not safe to remove it */ plugin_module_make_resident (geany_plugin); - /* webkit uses threads but don't initialize the thread system */ - if (! g_thread_supported ()) { - g_thread_init (NULL); - } - load_config (); gwh_keybindings_init (); @@ -460,6 +462,9 @@ plugin_init (GeanyData *data) keybindings_set_item (gwh_keybindings_get_group (), GWH_KB_TOGGLE_BOOKMARK, on_kb_toggle_bookmark, 0, 0, "toggle_bookmark", _("Toggle bookmark for the current website"), NULL); + keybindings_set_item (gwh_keybindings_get_group (), GWH_KB_LOAD_CURRENT_FILE, + on_kb_load_current_file, 0, 0, "load_current_file", + _("Load the current file in the web view"), NULL); } void @@ -522,11 +527,11 @@ plugin_configure (GtkDialog *dialog) cdialog = g_malloc (sizeof *cdialog); /* Top-level box, containing the different frames */ - box1 = gtk_vbox_new (FALSE, 12); + box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); /* Browser */ gtk_box_pack_start (GTK_BOX (box1), ui_frame_new_with_alignment (_("Browser"), &alignment), FALSE, FALSE, 0); - box = gtk_vbox_new (FALSE, 0); + box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (alignment), box); /* browser position */ cdialog->browser_position = gwh_settings_widget_new (G_settings, "browser-position"); @@ -538,7 +543,7 @@ plugin_configure (GtkDialog *dialog) /* Windows */ gtk_box_pack_start (GTK_BOX (box1), ui_frame_new_with_alignment (_("Windows"), &alignment), FALSE, FALSE, 0); - box = gtk_vbox_new (FALSE, 0); + box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (alignment), box); /* skip taskbar */ cdialog->secondary_windows_skip_taskbar = gwh_settings_widget_new (G_settings, diff --git a/webhelper/src/gwh-settings.c b/webhelper/src/gwh-settings.c index 9e785781c..014f6baa3 100644 --- a/webhelper/src/gwh-settings.c +++ b/webhelper/src/gwh-settings.c @@ -35,7 +35,7 @@ struct _GwhSettingsPrivate }; -G_DEFINE_TYPE (GwhSettings, gwh_settings, G_TYPE_OBJECT) +G_DEFINE_TYPE_WITH_PRIVATE (GwhSettings, gwh_settings, G_TYPE_OBJECT) static void @@ -124,15 +124,12 @@ gwh_settings_class_init (GwhSettingsClass *klass) object_class->finalize = gwh_settings_finalize; object_class->get_property = gwh_settings_get_property; object_class->set_property = gwh_settings_set_property; - - g_type_class_add_private (klass, sizeof (GwhSettingsPrivate)); } static void gwh_settings_init (GwhSettings *self) { - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GWH_TYPE_SETTINGS, - GwhSettingsPrivate); + self->priv = gwh_settings_get_instance_private (self); self->priv->prop_array = g_ptr_array_new (); } @@ -189,7 +186,7 @@ gwh_settings_install_property (GwhSettings *self, break; HANDLE_BASIC_TYPE (BOOLEAN, Boolean, boolean) - HANDLE_BASIC_TYPE (CHAR, Char, char) + HANDLE_BASIC_TYPE (CHAR, Char, schar) HANDLE_BASIC_TYPE (UCHAR, UChar, uchar) HANDLE_BASIC_TYPE (INT, Int, int) HANDLE_BASIC_TYPE (UINT, UInt, uint) diff --git a/workbench/src/sidebar.c b/workbench/src/sidebar.c index 4e5c8fe47..0b6da7b2f 100644 --- a/workbench/src/sidebar.c +++ b/workbench/src/sidebar.c @@ -213,6 +213,8 @@ static void sidebar_create_branch(gint level, const gchar *abs_base_dir, GSList FILEVIEW_COLUMN_ICON, icon_dir, FILEVIEW_COLUMN_NAME, last_dir_name, FILEVIEW_COLUMN_DATA_ID, DATA_ID_SUB_DIRECTORY, + /* cppcheck-suppress leakNoVarFunctionCall + * type is gpointer, but admittedly I don't see where it's freed? */ FILEVIEW_COLUMN_ASSIGNED_DATA_POINTER, g_strdup(full), -1); @@ -235,6 +237,8 @@ static void sidebar_create_branch(gint level, const gchar *abs_base_dir, GSList FILEVIEW_COLUMN_ICON, icon_dir, FILEVIEW_COLUMN_NAME, last_dir_name, FILEVIEW_COLUMN_DATA_ID, DATA_ID_SUB_DIRECTORY, + /* cppcheck-suppress leakNoVarFunctionCall + * type is gpointer, but admittedly I don't see where it's freed? */ FILEVIEW_COLUMN_ASSIGNED_DATA_POINTER, g_strdup(full), -1); g_free(full); @@ -440,6 +444,8 @@ static void sidebar_add_file (WB_PROJECT *prj, WB_PROJECT_DIR *root, const gchar FILEVIEW_COLUMN_ICON, icon, FILEVIEW_COLUMN_NAME, name, FILEVIEW_COLUMN_DATA_ID, dataid, + /* cppcheck-suppress leakNoVarFunctionCall + * type is gpointer, but admittedly I don't see where it's freed? */ FILEVIEW_COLUMN_ASSIGNED_DATA_POINTER, g_strdup(filepath), -1); diff --git a/workbench/src/wb_project.c b/workbench/src/wb_project.c index 626f8e149..041c3a5f8 100644 --- a/workbench/src/wb_project.c +++ b/workbench/src/wb_project.c @@ -691,6 +691,7 @@ static guint wb_project_dir_rescan_int(WB_PROJECT *prj, WB_PROJECT_DIR *root) if (path) { + /* cppcheck-suppress leakNoVarFunctionCall -- key is freed automatically */ g_hash_table_add(root->file_table, g_strdup(path)); filenum++; } @@ -757,6 +758,7 @@ static void wb_project_dir_add_file_int(WB_PROJECT *prj, WB_PROJECT_DIR *root, c } /* Update file table and counters. */ + /* cppcheck-suppress leakNoVarFunctionCall -- key is freed automatically */ g_hash_table_add(root->file_table, g_strdup(filepath)); if (g_file_test(filepath, G_FILE_TEST_IS_DIR)) { @@ -818,6 +820,7 @@ static void wb_project_dir_update_tags(WB_PROJECT_DIR *root) gchar *locale_path = utils_get_locale_from_utf8(utf8_path); g_ptr_array_add(files, g_strdup(key)); + /* cppcheck-suppress leakNoVarFunctionCall -- key is freed automatically */ g_hash_table_add(root->file_table, g_strdup(utf8_path)); g_free(locale_path); } @@ -960,6 +963,7 @@ static void wb_project_dir_regenerate_tags(WB_PROJECT_DIR *root, G_GNUC_UNUSED g } /* Add all files to the file-table (files and dirs)! */ + /* cppcheck-suppress leakNoVarFunctionCall -- key is freed automatically */ g_hash_table_add(file_table, g_strdup(key)); } g_hash_table_destroy(root->file_table); diff --git a/workbench/src/workbench.c b/workbench/src/workbench.c index 30c45d3b7..9dbbc8201 100644 --- a/workbench/src/workbench.c +++ b/workbench/src/workbench.c @@ -833,6 +833,8 @@ gboolean workbench_load(WORKBENCH *wb, const gchar *filename, GError **error) return FALSE; } + g_free (contents); + if (g_key_file_has_key (kf, "General", "filetype", NULL) && g_key_file_has_key (kf, "General", "version", NULL)) { @@ -854,6 +856,7 @@ gboolean workbench_load(WORKBENCH *wb, const gchar *filename, GError **error) g_set_error (error, 0, 0, _("File %s is not a valid workbench file!"), filename); + g_key_file_free (kf); return FALSE; } workbench_set_filename(wb, filename); @@ -964,7 +967,6 @@ gboolean workbench_load(WORKBENCH *wb, const gchar *filename, GError **error) } g_key_file_free(kf); - g_free (contents); success = TRUE; } else if (error != NULL)