From 1a4602c3aed04c5294eb9a9613ce93283b79f5fb Mon Sep 17 00:00:00 2001 From: "raveit65 (via Travis CI)" Date: Sun, 18 Feb 2024 23:59:08 +0000 Subject: Deploy mate-desktop/pluma to github.com/mate-desktop/pluma.git:gh-pages --- .../index.html | 146 + .../report-008555.html | 1944 +++++++ .../report-13aee1.html | 1139 ++++ .../report-1e519c.html | 1475 ++++++ .../report-222690.html | 5495 ++++++++++++++++++++ .../report-4a60ca.html | 4233 +++++++++++++++ .../report-527848.html | 1327 +++++ .../report-5f782a.html | 1544 ++++++ .../report-6c7faf.html | 1444 +++++ .../report-731a91.html | 4342 ++++++++++++++++ .../report-7b3428.html | 4233 +++++++++++++++ .../report-a608c3.html | 1327 +++++ .../report-b8f564.html | 2089 ++++++++ .../report-cf3974.html | 2089 ++++++++ .../report-efdf48.html | 1150 ++++ .../report-f2c91f.html | 1120 ++++ .../scanview.css | 62 + .../sorttable.js | 492 ++ 18 files changed, 35651 insertions(+) create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/index.html create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-008555.html create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-13aee1.html create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-1e519c.html create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-222690.html create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-4a60ca.html create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-527848.html create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-5f782a.html create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-6c7faf.html create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-731a91.html create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-7b3428.html create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-a608c3.html create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-b8f564.html create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-cf3974.html create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-efdf48.html create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-f2c91f.html create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/scanview.css create mode 100644 2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/sorttable.js (limited to '2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item') diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/index.html b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/index.html new file mode 100644 index 00000000..aef8bb66 --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/index.html @@ -0,0 +1,146 @@ + + +rootdir - scan-build results + + + + + + +

rootdir - scan-build results

+ + + + + + + +
User:root@bccecf2a327a
Working Directory:/rootdir
Command Line:make -j 2
Clang Version:clang version 16.0.6 (Fedora 16.0.6-3.fc38) +
Date:Sun Oct 22 11:44:45 2023
+

Bug Summary

+ + + + + + + + + + + + + + +
Bug TypeQuantityDisplay?
All Bugs15
Logic error
Cast from non-struct type to struct type2
Identical branches1
Out-of-bound access3
Use fixed address1
Memory error
Use-after-free1
Security
Potential insecure memory buffer bounds restriction in call 'strcpy'1
Unused code
Dead assignment5
Dead nested assignment1
+

Reports

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Bug GroupBug Type ▾FileFunction/MethodLinePath Length
Logic errorCast from non-struct type to struct typepluma/mate-submodules/libegg/eggsmclient-xsmp.carray_prop11991View Report
Logic errorCast from non-struct type to struct typepluma/mate-submodules/libegg/eggsmclient-xsmp.cptrarray_prop12321View Report
Unused codeDead assignmentplugins/filebrowser/pluma-file-browser-view.ckey_press_event6311View Report
Unused codeDead assignmentplugins/taglist/pluma-taglist-plugin-panel.cinsert_tag1941View Report
Unused codeDead assignmentplugins/filebrowser/pluma-file-browser-store.cpluma_file_browser_store_get_iter5771View Report
Unused codeDead assignmentpluma/plumatextregion.cpluma_text_region_subtract3321View Report
Unused codeDead assignmentpluma/plumatextregion.cpluma_text_region_add2651View Report
Unused codeDead nested assignmentplugins/filebrowser/pluma-file-browser-store.cmodel_add_nodes_from_files20591View Report
Logic errorIdentical branchesplugins/spell/pluma-spell-checker-language.cload_iso_entries1951View Report
Logic errorOut-of-bound accesspluma/pluma-document-output-stream.cpluma_document_output_stream_write33215View Report
Logic errorOut-of-bound accessplugins/filebrowser/pluma-file-browser-store.cmodel_resort_node111032View Report
Logic errorOut-of-bound accesspluma/bacon-message-connection.cserver_cb16926View Report
SecurityPotential insecure memory buffer bounds restriction in call 'strcpy'pluma/pluma-window.cpluma_window_key_press_event3321View Report
Logic errorUse fixed addresstests/document-saver.csaver_test_data_new6812View Report
Memory errorUse-after-freeplugins/spell/pluma-spell-checker-dialog.cpluma_spell_checker_dialog_set_misspelled_word41148View Report
+ + diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-008555.html b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-008555.html new file mode 100644 index 00000000..fe81da38 --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-008555.html @@ -0,0 +1,1944 @@ + + + +pluma-file-browser-view.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:plugins/filebrowser/pluma-file-browser-view.c
Warning:line 631, column 2
Value stored to 'handled' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pluma-file-browser-view.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/plugins/filebrowser -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I ../.. -I ../.. -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/gtksourceview-4 -I /usr/include/libpeas-1.0 -I /usr/include/gobject-introspection-1.0 -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/plugins/filebrowser -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-10-22-114445-13211-1 -x c pluma-file-browser-view.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * pluma-file-browser-view.c - Pluma plugin providing easy file access
3 * from the sidepanel
4 *
5 * Copyright (C) 2006 - Jesse van den Kieboom <jesse@icecrew.nl>
6 * Copyright (C) 2012-2021 MATE Developers
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23#include <string.h>
24#include <gio/gio.h>
25#include <gtk/gtk.h>
26#include <gdk/gdkkeysyms.h>
27
28#include "pluma-file-browser-store.h"
29#include "pluma-file-bookmarks-store.h"
30#include "pluma-file-browser-view.h"
31#include "pluma-file-browser-enum-types.h"
32
33struct _PlumaFileBrowserViewPrivate
34{
35 GtkTreeViewColumn *column;
36 GtkCellRenderer *pixbuf_renderer;
37 GtkCellRenderer *text_renderer;
38
39 GtkTreeModel *model;
40 GtkTreeRowReference *editable;
41
42 GdkCursor *busy_cursor;
43
44 /* CLick policy */
45 PlumaFileBrowserViewClickPolicy click_policy;
46 GtkTreePath *double_click_path[2]; /* Both clicks in a double click need to be on the same row */
47 GtkTreePath *hover_path;
48 GdkCursor *hand_cursor;
49 gboolean ignore_release;
50 gboolean selected_on_button_down;
51 gint drag_button;
52 gboolean drag_started;
53
54 gboolean restore_expand_state;
55 gboolean is_refresh;
56 GHashTable * expand_state;
57};
58
59/* Properties */
60enum
61{
62 PROP_0,
63
64 PROP_CLICK_POLICY,
65 PROP_RESTORE_EXPAND_STATE
66};
67
68/* Signals */
69enum
70{
71 ERROR,
72 FILE_ACTIVATED,
73 DIRECTORY_ACTIVATED,
74 BOOKMARK_ACTIVATED,
75 NUM_SIGNALS
76};
77
78static guint signals[NUM_SIGNALS] = { 0 };
79
80static const GtkTargetEntry drag_source_targets[] = {
81 { "text/uri-list", 0, 0 }
82};
83
84G_DEFINE_DYNAMIC_TYPE_EXTENDED (PlumaFileBrowserView,static void pluma_file_browser_view_init (PlumaFileBrowserView
*self); static void pluma_file_browser_view_class_init (PlumaFileBrowserViewClass
*klass); static void pluma_file_browser_view_class_finalize (
PlumaFileBrowserViewClass *klass); static gpointer pluma_file_browser_view_parent_class
= ((void*)0); static GType pluma_file_browser_view_type_id =
0; static gint PlumaFileBrowserView_private_offset; static void
pluma_file_browser_view_class_intern_init (gpointer klass) {
pluma_file_browser_view_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserView_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserView_private_offset); pluma_file_browser_view_class_init
((PlumaFileBrowserViewClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_view_get_instance_private
(PlumaFileBrowserView *self) { return (((gpointer) ((guint8*
) (self) + (glong) (PlumaFileBrowserView_private_offset)))); }
GType pluma_file_browser_view_get_type (void) { return pluma_file_browser_view_type_id
; } static void pluma_file_browser_view_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserViewClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_view_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_view_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserView), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_view_init, ((void*)0) };
pluma_file_browser_view_type_id = g_type_module_register_type
(type_module, (gtk_tree_view_get_type ()), "PlumaFileBrowserView"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_view_type_id; { { PlumaFileBrowserView_private_offset
= sizeof (PlumaFileBrowserViewPrivate); } ; } }
85 pluma_file_browser_view,static void pluma_file_browser_view_init (PlumaFileBrowserView
*self); static void pluma_file_browser_view_class_init (PlumaFileBrowserViewClass
*klass); static void pluma_file_browser_view_class_finalize (
PlumaFileBrowserViewClass *klass); static gpointer pluma_file_browser_view_parent_class
= ((void*)0); static GType pluma_file_browser_view_type_id =
0; static gint PlumaFileBrowserView_private_offset; static void
pluma_file_browser_view_class_intern_init (gpointer klass) {
pluma_file_browser_view_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserView_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserView_private_offset); pluma_file_browser_view_class_init
((PlumaFileBrowserViewClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_view_get_instance_private
(PlumaFileBrowserView *self) { return (((gpointer) ((guint8*
) (self) + (glong) (PlumaFileBrowserView_private_offset)))); }
GType pluma_file_browser_view_get_type (void) { return pluma_file_browser_view_type_id
; } static void pluma_file_browser_view_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserViewClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_view_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_view_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserView), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_view_init, ((void*)0) };
pluma_file_browser_view_type_id = g_type_module_register_type
(type_module, (gtk_tree_view_get_type ()), "PlumaFileBrowserView"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_view_type_id; { { PlumaFileBrowserView_private_offset
= sizeof (PlumaFileBrowserViewPrivate); } ; } }
86 GTK_TYPE_TREE_VIEW,static void pluma_file_browser_view_init (PlumaFileBrowserView
*self); static void pluma_file_browser_view_class_init (PlumaFileBrowserViewClass
*klass); static void pluma_file_browser_view_class_finalize (
PlumaFileBrowserViewClass *klass); static gpointer pluma_file_browser_view_parent_class
= ((void*)0); static GType pluma_file_browser_view_type_id =
0; static gint PlumaFileBrowserView_private_offset; static void
pluma_file_browser_view_class_intern_init (gpointer klass) {
pluma_file_browser_view_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserView_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserView_private_offset); pluma_file_browser_view_class_init
((PlumaFileBrowserViewClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_view_get_instance_private
(PlumaFileBrowserView *self) { return (((gpointer) ((guint8*
) (self) + (glong) (PlumaFileBrowserView_private_offset)))); }
GType pluma_file_browser_view_get_type (void) { return pluma_file_browser_view_type_id
; } static void pluma_file_browser_view_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserViewClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_view_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_view_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserView), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_view_init, ((void*)0) };
pluma_file_browser_view_type_id = g_type_module_register_type
(type_module, (gtk_tree_view_get_type ()), "PlumaFileBrowserView"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_view_type_id; { { PlumaFileBrowserView_private_offset
= sizeof (PlumaFileBrowserViewPrivate); } ; } }
87 0,static void pluma_file_browser_view_init (PlumaFileBrowserView
*self); static void pluma_file_browser_view_class_init (PlumaFileBrowserViewClass
*klass); static void pluma_file_browser_view_class_finalize (
PlumaFileBrowserViewClass *klass); static gpointer pluma_file_browser_view_parent_class
= ((void*)0); static GType pluma_file_browser_view_type_id =
0; static gint PlumaFileBrowserView_private_offset; static void
pluma_file_browser_view_class_intern_init (gpointer klass) {
pluma_file_browser_view_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserView_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserView_private_offset); pluma_file_browser_view_class_init
((PlumaFileBrowserViewClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_view_get_instance_private
(PlumaFileBrowserView *self) { return (((gpointer) ((guint8*
) (self) + (glong) (PlumaFileBrowserView_private_offset)))); }
GType pluma_file_browser_view_get_type (void) { return pluma_file_browser_view_type_id
; } static void pluma_file_browser_view_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserViewClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_view_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_view_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserView), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_view_init, ((void*)0) };
pluma_file_browser_view_type_id = g_type_module_register_type
(type_module, (gtk_tree_view_get_type ()), "PlumaFileBrowserView"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_view_type_id; { { PlumaFileBrowserView_private_offset
= sizeof (PlumaFileBrowserViewPrivate); } ; } }
88 G_ADD_PRIVATE_DYNAMIC (PlumaFileBrowserView))static void pluma_file_browser_view_init (PlumaFileBrowserView
*self); static void pluma_file_browser_view_class_init (PlumaFileBrowserViewClass
*klass); static void pluma_file_browser_view_class_finalize (
PlumaFileBrowserViewClass *klass); static gpointer pluma_file_browser_view_parent_class
= ((void*)0); static GType pluma_file_browser_view_type_id =
0; static gint PlumaFileBrowserView_private_offset; static void
pluma_file_browser_view_class_intern_init (gpointer klass) {
pluma_file_browser_view_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserView_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserView_private_offset); pluma_file_browser_view_class_init
((PlumaFileBrowserViewClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_view_get_instance_private
(PlumaFileBrowserView *self) { return (((gpointer) ((guint8*
) (self) + (glong) (PlumaFileBrowserView_private_offset)))); }
GType pluma_file_browser_view_get_type (void) { return pluma_file_browser_view_type_id
; } static void pluma_file_browser_view_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserViewClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_view_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_view_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserView), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_view_init, ((void*)0) };
pluma_file_browser_view_type_id = g_type_module_register_type
(type_module, (gtk_tree_view_get_type ()), "PlumaFileBrowserView"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_view_type_id; { { PlumaFileBrowserView_private_offset
= sizeof (PlumaFileBrowserViewPrivate); } ; } }
89
90static void on_cell_edited (GtkCellRendererText * cell,
91 gchar * path,
92 gchar * new_text,
93 PlumaFileBrowserView * tree_view);
94
95static void on_begin_refresh (PlumaFileBrowserStore * model,
96 PlumaFileBrowserView * view);
97static void on_end_refresh (PlumaFileBrowserStore * model,
98 PlumaFileBrowserView * view);
99
100static void on_unload (PlumaFileBrowserStore * model,
101 gchar const * uri,
102 PlumaFileBrowserView * view);
103
104static void on_row_inserted (PlumaFileBrowserStore * model,
105 GtkTreePath * path,
106 GtkTreeIter * iter,
107 PlumaFileBrowserView * view);
108
109static void
110pluma_file_browser_view_finalize (GObject * object)
111{
112 PlumaFileBrowserView *obj = PLUMA_FILE_BROWSER_VIEW(object)((((PlumaFileBrowserView*) (void *) ((object)))));
113
114 if (obj->priv->hand_cursor)
115 g_object_unref (obj->priv->hand_cursor);
116
117 if (obj->priv->hover_path)
118 gtk_tree_path_free (obj->priv->hover_path);
119
120 if (obj->priv->expand_state)
121 {
122 g_hash_table_destroy (obj->priv->expand_state);
123 obj->priv->expand_state = NULL((void*)0);
124 }
125
126 g_object_unref (obj->priv->busy_cursor);
127
128 G_OBJECT_CLASS (pluma_file_browser_view_parent_class)((((GObjectClass*) (void *) ((pluma_file_browser_view_parent_class
)))))
->
129 finalize (object);
130}
131
132static void
133add_expand_state (PlumaFileBrowserView * view,
134 gchar const * uri)
135{
136 GFile * file;
137
138 if (!uri)
139 return;
140
141 file = g_file_new_for_uri (uri);
142
143 if (view->priv->expand_state)
144 g_hash_table_insert (view->priv->expand_state, file, file);
145 else
146 g_object_unref (file);
147}
148
149static void
150remove_expand_state (PlumaFileBrowserView * view,
151 gchar const * uri)
152{
153 GFile * file;
154
155 if (!uri)
156 return;
157
158 file = g_file_new_for_uri (uri);
159
160 if (view->priv->expand_state)
161 g_hash_table_remove (view->priv->expand_state, file);
162
163 g_object_unref (file);
164}
165
166static void
167row_expanded (GtkTreeView * tree_view,
168 GtkTreeIter * iter,
169 GtkTreePath * path)
170{
171 PlumaFileBrowserView *view = PLUMA_FILE_BROWSER_VIEW (tree_view)((((PlumaFileBrowserView*) (void *) ((tree_view)))));
172 gchar * uri;
173
174 if (GTK_TREE_VIEW_CLASS (pluma_file_browser_view_parent_class)((((GtkTreeViewClass*) (void *) ((pluma_file_browser_view_parent_class
)))))
->row_expanded)
175 GTK_TREE_VIEW_CLASS (pluma_file_browser_view_parent_class)((((GtkTreeViewClass*) (void *) ((pluma_file_browser_view_parent_class
)))))
->row_expanded (tree_view, iter, path);
176
177 if (!PLUMA_IS_FILE_BROWSER_STORE (view->priv->model)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(view->priv->model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
178 return;
179
180 if (view->priv->restore_expand_state)
181 {
182 gtk_tree_model_get (view->priv->model,
183 iter,
184 PLUMA_FILE_BROWSER_STORE_COLUMN_URI,
185 &uri,
186 -1);
187
188 add_expand_state (view, uri);
189 g_free (uri);
190 }
191
192 _pluma_file_browser_store_iter_expanded (PLUMA_FILE_BROWSER_STORE (view->priv->model)((((PlumaFileBrowserStore*) (void *) ((view->priv->model
)))))
,
193 iter);
194}
195
196static void
197row_collapsed (GtkTreeView * tree_view,
198 GtkTreeIter * iter,
199 GtkTreePath * path)
200{
201 PlumaFileBrowserView *view = PLUMA_FILE_BROWSER_VIEW (tree_view)((((PlumaFileBrowserView*) (void *) ((tree_view)))));
202 gchar * uri;
203
204 if (GTK_TREE_VIEW_CLASS (pluma_file_browser_view_parent_class)((((GtkTreeViewClass*) (void *) ((pluma_file_browser_view_parent_class
)))))
->row_collapsed)
205 GTK_TREE_VIEW_CLASS (pluma_file_browser_view_parent_class)((((GtkTreeViewClass*) (void *) ((pluma_file_browser_view_parent_class
)))))
->row_collapsed (tree_view, iter, path);
206
207 if (!PLUMA_IS_FILE_BROWSER_STORE (view->priv->model)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(view->priv->model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
208 return;
209
210 if (view->priv->restore_expand_state)
211 {
212 gtk_tree_model_get (view->priv->model,
213 iter,
214 PLUMA_FILE_BROWSER_STORE_COLUMN_URI,
215 &uri,
216 -1);
217
218 remove_expand_state (view, uri);
219 g_free (uri);
220 }
221
222 _pluma_file_browser_store_iter_collapsed (PLUMA_FILE_BROWSER_STORE (view->priv->model)((((PlumaFileBrowserStore*) (void *) ((view->priv->model
)))))
,
223 iter);
224}
225
226static gboolean
227leave_notify_event (GtkWidget *widget,
228 GdkEventCrossing *event)
229{
230 PlumaFileBrowserView *view = PLUMA_FILE_BROWSER_VIEW (widget)((((PlumaFileBrowserView*) (void *) ((widget)))));
231
232 if (view->priv->click_policy == PLUMA_FILE_BROWSER_VIEW_CLICK_POLICY_SINGLE &&
233 view->priv->hover_path != NULL((void*)0)) {
234 gtk_tree_path_free (view->priv->hover_path);
235 view->priv->hover_path = NULL((void*)0);
236 }
237
238 // Chainup
239 return GTK_WIDGET_CLASS (pluma_file_browser_view_parent_class)((((GtkWidgetClass*) (void *) ((pluma_file_browser_view_parent_class
)))))
->leave_notify_event (widget, event);
240}
241
242static gboolean
243enter_notify_event (GtkWidget *widget,
244 GdkEventCrossing *event)
245{
246 PlumaFileBrowserView *view = PLUMA_FILE_BROWSER_VIEW (widget)((((PlumaFileBrowserView*) (void *) ((widget)))));
247
248 if (view->priv->click_policy == PLUMA_FILE_BROWSER_VIEW_CLICK_POLICY_SINGLE) {
249 if (view->priv->hover_path != NULL((void*)0))
250 gtk_tree_path_free (view->priv->hover_path);
251
252 gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget)((((GtkTreeView*) (void *) ((widget))))),
253 event->x, event->y,
254 &view->priv->hover_path,
255 NULL((void*)0), NULL((void*)0), NULL((void*)0));
256
257 if (view->priv->hover_path != NULL((void*)0))
258 gdk_window_set_cursor (gtk_widget_get_window (widget),
259 view->priv->hand_cursor);
260 }
261
262 // Chainup
263 return GTK_WIDGET_CLASS (pluma_file_browser_view_parent_class)((((GtkWidgetClass*) (void *) ((pluma_file_browser_view_parent_class
)))))
->enter_notify_event (widget, event);
264}
265
266static gboolean
267motion_notify_event (GtkWidget * widget,
268 GdkEventMotion * event)
269{
270 GtkTreePath *old_hover_path;
271 PlumaFileBrowserView *view = PLUMA_FILE_BROWSER_VIEW (widget)((((PlumaFileBrowserView*) (void *) ((widget)))));
272
273 if (view->priv->click_policy == PLUMA_FILE_BROWSER_VIEW_CLICK_POLICY_SINGLE) {
274 old_hover_path = view->priv->hover_path;
275 gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget)((((GtkTreeView*) (void *) ((widget))))),
276 event->x, event->y,
277 &view->priv->hover_path,
278 NULL((void*)0), NULL((void*)0), NULL((void*)0));
279
280 if ((old_hover_path != NULL((void*)0)) != (view->priv->hover_path != NULL((void*)0))) {
281 if (view->priv->hover_path != NULL((void*)0))
282 gdk_window_set_cursor (gtk_widget_get_window (widget),
283 view->priv->hand_cursor);
284 else
285 gdk_window_set_cursor (gtk_widget_get_window (widget),
286 NULL((void*)0));
287 }
288
289 if (old_hover_path != NULL((void*)0))
290 gtk_tree_path_free (old_hover_path);
291 }
292
293 // Chainup
294 return GTK_WIDGET_CLASS (pluma_file_browser_view_parent_class)((((GtkWidgetClass*) (void *) ((pluma_file_browser_view_parent_class
)))))
->motion_notify_event (widget, event);
295}
296
297static void
298set_click_policy_property (PlumaFileBrowserView *obj,
299 PlumaFileBrowserViewClickPolicy click_policy)
300{
301 GtkTreeIter iter;
302 GdkDisplay *display;
303 GdkWindow *win;
304
305 display = gtk_widget_get_display (GTK_WIDGET (obj)((((GtkWidget*) (void *) ((obj))))));
306
307 obj->priv->click_policy = click_policy;
308
309 if (click_policy == PLUMA_FILE_BROWSER_VIEW_CLICK_POLICY_SINGLE) {
310 if (obj->priv->hand_cursor == NULL((void*)0))
311 obj->priv->hand_cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
312 } else if (click_policy == PLUMA_FILE_BROWSER_VIEW_CLICK_POLICY_DOUBLE) {
313 if (obj->priv->hover_path != NULL((void*)0)) {
314 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (obj->priv->model)((((GtkTreeModel*) (void *) ((obj->priv->model))))),
315 &iter, obj->priv->hover_path))
316 gtk_tree_model_row_changed (GTK_TREE_MODEL (obj->priv->model)((((GtkTreeModel*) (void *) ((obj->priv->model))))),
317 obj->priv->hover_path, &iter);
318
319 gtk_tree_path_free (obj->priv->hover_path);
320 obj->priv->hover_path = NULL((void*)0);
321 }
322
323 if (gtk_widget_get_realized (GTK_WIDGET (obj)((((GtkWidget*) (void *) ((obj))))))) {
324 win = gtk_widget_get_window (GTK_WIDGET (obj)((((GtkWidget*) (void *) ((obj))))));
325 gdk_window_set_cursor (win, NULL((void*)0));
326
327 display = gtk_widget_get_display (GTK_WIDGET (obj)((((GtkWidget*) (void *) ((obj))))));
328
329 if (display != NULL((void*)0))
330 gdk_display_flush (display);
331 }
332
333 if (obj->priv->hand_cursor) {
334 g_object_unref (obj->priv->hand_cursor);
335 obj->priv->hand_cursor = NULL((void*)0);
336 }
337 }
338}
339
340static void
341directory_activated (PlumaFileBrowserView *view,
342 GtkTreeIter *iter)
343{
344 pluma_file_browser_store_set_virtual_root (PLUMA_FILE_BROWSER_STORE (view->priv->model)((((PlumaFileBrowserStore*) (void *) ((view->priv->model
)))))
, iter);
345}
346
347static void
348activate_selected_files (PlumaFileBrowserView *view) {
349 GtkTreeView *tree_view = GTK_TREE_VIEW (view)((((GtkTreeView*) (void *) ((view)))));
350 GtkTreeSelection *selection = gtk_tree_view_get_selection (tree_view);
351 GList *rows, *row;
352 GtkTreePath *directory = NULL((void*)0);
353 GtkTreePath *path;
354 GtkTreeIter iter;
355 PlumaFileBrowserStoreFlag flags;
356
357 rows = gtk_tree_selection_get_selected_rows (selection, &view->priv->model);
358
359 for (row = rows; row; row = row->next) {
360 path = (GtkTreePath *)(row->data);
361
362 /* Get iter from path */
363 if (!gtk_tree_model_get_iter (view->priv->model, &iter, path))
364 continue;
365
366 gtk_tree_model_get (view->priv->model, &iter, PLUMA_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags, -1);
367
368 if (FILE_IS_DIR (flags)(flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY)) {
369 if (directory == NULL((void*)0))
370 directory = path;
371
372 } else if (!FILE_IS_DUMMY (flags)(flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY)) {
373 g_signal_emit (view, signals[FILE_ACTIVATED], 0, &iter);
374 }
375 }
376
377 if (directory != NULL((void*)0)) {
378 if (gtk_tree_model_get_iter (view->priv->model, &iter, directory))
379 g_signal_emit (view, signals[DIRECTORY_ACTIVATED], 0, &iter);
380 }
381
382 g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free);
383}
384
385static void
386activate_selected_bookmark (PlumaFileBrowserView *view) {
387 GtkTreeView *tree_view = GTK_TREE_VIEW (view)((((GtkTreeView*) (void *) ((view)))));
388 GtkTreeSelection *selection = gtk_tree_view_get_selection (tree_view);
389 GtkTreeIter iter;
390
391 if (gtk_tree_selection_get_selected (selection, &view->priv->model, &iter))
392 g_signal_emit (view, signals[BOOKMARK_ACTIVATED], 0, &iter);
393}
394
395static void
396activate_selected_items (PlumaFileBrowserView *view)
397{
398 if (PLUMA_IS_FILE_BROWSER_STORE (view->priv->model)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(view->priv->model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
399 activate_selected_files (view);
400 else if (PLUMA_IS_FILE_BOOKMARKS_STORE (view->priv->model)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(view->priv->model)); GType __t = ((pluma_file_bookmarks_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
401 activate_selected_bookmark (view);
402}
403
404static void
405toggle_hidden_filter (PlumaFileBrowserView *view)
406{
407 PlumaFileBrowserStoreFilterMode mode;
408
409 if (PLUMA_IS_FILE_BROWSER_STORE (view->priv->model)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(view->priv->model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
410 {
411 mode = pluma_file_browser_store_get_filter_mode
412 (PLUMA_FILE_BROWSER_STORE (view->priv->model)((((PlumaFileBrowserStore*) (void *) ((view->priv->model
)))))
);
413 mode ^= PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_HIDDEN;
414 pluma_file_browser_store_set_filter_mode
415 (PLUMA_FILE_BROWSER_STORE (view->priv->model)((((PlumaFileBrowserStore*) (void *) ((view->priv->model
)))))
, mode);
416 }
417}
418
419static gboolean
420button_event_modifies_selection (GdkEventButton *event)
421{
422 return (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) != 0;
423}
424
425static void
426drag_begin (GtkWidget *widget,
427 GdkDragContext *context)
428{
429 PlumaFileBrowserView *view = PLUMA_FILE_BROWSER_VIEW (widget)((((PlumaFileBrowserView*) (void *) ((widget)))));
430
431 view->priv->drag_button = 0;
432 view->priv->drag_started = TRUE(!(0));
433
434 /* Chain up */
435 GTK_WIDGET_CLASS (pluma_file_browser_view_parent_class)((((GtkWidgetClass*) (void *) ((pluma_file_browser_view_parent_class
)))))
->drag_begin (widget, context);
436}
437
438static void
439did_not_drag (PlumaFileBrowserView *view,
440 GdkEventButton *event)
441{
442 GtkTreeView *tree_view;
443 GtkTreeSelection *selection;
444 GtkTreePath *path;
445
446 tree_view = GTK_TREE_VIEW (view)((((GtkTreeView*) (void *) ((view)))));
447 selection = gtk_tree_view_get_selection (tree_view);
448
449 if (gtk_tree_view_get_path_at_pos (tree_view, event->x, event->y,
450 &path, NULL((void*)0), NULL((void*)0), NULL((void*)0))) {
451 if ((view->priv->click_policy == PLUMA_FILE_BROWSER_VIEW_CLICK_POLICY_SINGLE)
452 && !button_event_modifies_selection(event)
453 && (event->button == 1 || event->button == 2)) {
454 /* Activate all selected items, and leave them selected */
455 activate_selected_items (view);
456 } else if ((event->button == 1 || event->button == 2)
457 && ((event->state & GDK_CONTROL_MASK) != 0 ||
458 (event->state & GDK_SHIFT_MASK) == 0)
459 && view->priv->selected_on_button_down) {
460 if (!button_event_modifies_selection (event)) {
461 gtk_tree_selection_unselect_all (selection);
462 gtk_tree_selection_select_path (selection, path);
463 } else {
464 gtk_tree_selection_unselect_path (selection, path);
465 }
466 }
467
468 gtk_tree_path_free (path);
469 }
470}
471
472static gboolean
473button_release_event (GtkWidget *widget,
474 GdkEventButton *event)
475{
476 PlumaFileBrowserView *view = PLUMA_FILE_BROWSER_VIEW (widget)((((PlumaFileBrowserView*) (void *) ((widget)))));
477
478 if (event->button == view->priv->drag_button) {
479 view->priv->drag_button = 0;
480
481 if (!view->priv->drag_started &&
482 !view->priv->ignore_release)
483 did_not_drag (view, event);
484 }
485
486 /* Chain up */
487 return GTK_WIDGET_CLASS (pluma_file_browser_view_parent_class)((((GtkWidgetClass*) (void *) ((pluma_file_browser_view_parent_class
)))))
->button_release_event (widget, event);
488}
489
490static gboolean
491button_press_event (GtkWidget *widget,
492 GdkEventButton *event)
493{
494 int double_click_time;
495 static int click_count = 0;
496 static guint32 last_click_time = 0;
497 PlumaFileBrowserView *view;
498 GtkTreeView *tree_view;
499 GtkTreeSelection *selection;
500 GtkTreePath *path;
501 int expander_size;
502 int horizontal_separator;
503 gboolean on_expander;
504 gboolean call_parent;
505 gboolean selected;
506 GtkWidgetClass *widget_parent = GTK_WIDGET_CLASS(pluma_file_browser_view_parent_class)((((GtkWidgetClass*) (void *) ((pluma_file_browser_view_parent_class
)))))
;
507
508 tree_view = GTK_TREE_VIEW (widget)((((GtkTreeView*) (void *) ((widget)))));
509 view = PLUMA_FILE_BROWSER_VIEW (widget)((((PlumaFileBrowserView*) (void *) ((widget)))));
510 selection = gtk_tree_view_get_selection (tree_view);
511
512 /* Get double click time */
513 g_object_get (G_OBJECT (gtk_widget_get_settings (widget))((((GObject*) (void *) ((gtk_widget_get_settings (widget)))))
)
,
514 "gtk-double-click-time", &double_click_time,
515 NULL((void*)0));
516
517 /* Determine click count */
518 if (event->time - last_click_time < double_click_time)
519 click_count++;
520 else
521 click_count = 0;
522
523 last_click_time = event->time;
524
525 /* Ignore double click if we are in single click mode */
526 if (view->priv->click_policy == PLUMA_FILE_BROWSER_VIEW_CLICK_POLICY_SINGLE &&
527 click_count >= 2) {
528 return TRUE(!(0));
529 }
530
531 view->priv->ignore_release = FALSE(0);
532 call_parent = TRUE(!(0));
533
534 if (gtk_tree_view_get_path_at_pos (tree_view, event->x, event->y,
535 &path, NULL((void*)0), NULL((void*)0), NULL((void*)0))) {
536 /* Keep track of path of last click so double clicks only happen
537 * on the same item */
538 if ((event->button == 1 || event->button == 2) &&
539 event->type == GDK_BUTTON_PRESS) {
540 if (view->priv->double_click_path[1])
541 gtk_tree_path_free (view->priv->double_click_path[1]);
542
543 view->priv->double_click_path[1] = view->priv->double_click_path[0];
544 view->priv->double_click_path[0] = gtk_tree_path_copy (path);
545 }
546
547 if (event->type == GDK_2BUTTON_PRESS) {
548 if (view->priv->double_click_path[1] &&
549 gtk_tree_path_compare (view->priv->double_click_path[0], view->priv->double_click_path[1]) == 0)
550 activate_selected_items (view);
551
552 /* Chain up */
553 widget_parent->button_press_event (widget, event);
554 } else {
555 /* We're going to filter out some situations where
556 * we can't let the default code run because all
557 * but one row would be would be deselected. We don't
558 * want that; we want the right click menu or single
559 * click to apply to everything that's currently selected. */
560 selected = gtk_tree_selection_path_is_selected (selection, path);
561
562 if (event->button == 3 && selected)
563 call_parent = FALSE(0);
564
565 if ((event->button == 1 || event->button == 2) &&
566 ((event->state & GDK_CONTROL_MASK) != 0 ||
567 (event->state & GDK_SHIFT_MASK) == 0)) {
568 gtk_widget_style_get (widget,
569 "expander-size", &expander_size,
570 "horizontal-separator", &horizontal_separator,
571 NULL((void*)0));
572 on_expander = (event->x <= horizontal_separator / 2 +
573 gtk_tree_path_get_depth (path) * expander_size);
574
575 view->priv->selected_on_button_down = selected;
576
577 if (selected) {
578 call_parent = on_expander || gtk_tree_selection_count_selected_rows (selection) == 1;
579 view->priv->ignore_release = call_parent && view->priv->click_policy != PLUMA_FILE_BROWSER_VIEW_CLICK_POLICY_SINGLE;
580 } else if ((event->state & GDK_CONTROL_MASK) != 0) {
581 call_parent = FALSE(0);
582 gtk_tree_selection_select_path (selection, path);
583 } else {
584 view->priv->ignore_release = on_expander;
585 }
586 }
587
588 if (call_parent) {
589 /* Chain up */
590 widget_parent->button_press_event (widget, event);
591 } else if (selected) {
592 gtk_widget_grab_focus (widget);
593 }
594
595 if ((event->button == 1 || event->button == 2) &&
596 event->type == GDK_BUTTON_PRESS) {
597 view->priv->drag_started = FALSE(0);
598 view->priv->drag_button = event->button;
599 }
600 }
601
602 gtk_tree_path_free (path);
603 } else {
604 if ((event->button == 1 || event->button == 2) &&
605 event->type == GDK_BUTTON_PRESS) {
606 if (view->priv->double_click_path[1])
607 gtk_tree_path_free (view->priv->double_click_path[1]);
608
609 view->priv->double_click_path[1] = view->priv->double_click_path[0];
610 view->priv->double_click_path[0] = NULL((void*)0);
611 }
612
613 gtk_tree_selection_unselect_all (selection);
614 /* Chain up */
615 widget_parent->button_press_event (widget, event);
616 }
617
618 /* We already chained up if nescessary, so just return TRUE */
619 return TRUE(!(0));
620}
621
622static gboolean
623key_press_event (GtkWidget *widget,
624 GdkEventKey *event)
625{
626 PlumaFileBrowserView *view;
627 guint modifiers;
628 gboolean handled;
629
630 view = PLUMA_FILE_BROWSER_VIEW (widget)((((PlumaFileBrowserView*) (void *) ((widget)))));
631 handled = FALSE(0);
Value stored to 'handled' is never read
632
633 modifiers = gtk_accelerator_get_default_mod_mask ();
634
635 switch (event->keyval) {
636 case GDK_KEY_space0x020:
637 if (event->state & GDK_CONTROL_MASK) {
638 handled = FALSE(0);
639 break;
640 }
641 if (!gtk_widget_has_focus (widget)) {
642 handled = FALSE(0);
643 break;
644 }
645
646 activate_selected_items (view);
647 handled = TRUE(!(0));
648 break;
649
650 case GDK_KEY_Return0xff0d:
651 case GDK_KEY_KP_Enter0xff8d:
652 activate_selected_items (view);
653 handled = TRUE(!(0));
654 break;
655
656 case GDK_KEY_h0x068:
657 if ((event->state & modifiers) == GDK_CONTROL_MASK) {
658 toggle_hidden_filter (view);
659 handled = TRUE(!(0));
660 break;
661 }
662
663 default:
664 handled = FALSE(0);
665 }
666
667 /* Chain up */
668 if (!handled)
669 return GTK_WIDGET_CLASS (pluma_file_browser_view_parent_class)((((GtkWidgetClass*) (void *) ((pluma_file_browser_view_parent_class
)))))
->key_press_event (widget, event);
670
671 return TRUE(!(0));
672}
673
674static void
675fill_expand_state (PlumaFileBrowserView * view, GtkTreeIter * iter)
676{
677 GtkTreePath * path;
678 GtkTreeIter child;
679 gchar * uri;
680
681 if (!gtk_tree_model_iter_has_child (view->priv->model, iter))
682 return;
683
684 path = gtk_tree_model_get_path (view->priv->model, iter);
685
686 if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (view)((((GtkTreeView*) (void *) ((view))))), path))
687 {
688 gtk_tree_model_get (view->priv->model,
689 iter,
690 PLUMA_FILE_BROWSER_STORE_COLUMN_URI,
691 &uri,
692 -1);
693
694 add_expand_state (view, uri);
695 g_free (uri);
696 }
697
698 if (gtk_tree_model_iter_children (view->priv->model, &child, iter))
699 {
700 do {
701 fill_expand_state (view, &child);
702 } while (gtk_tree_model_iter_next (view->priv->model, &child));
703 }
704
705 gtk_tree_path_free (path);
706}
707
708static void
709uninstall_restore_signals (PlumaFileBrowserView * tree_view,
710 GtkTreeModel * model)
711{
712 g_signal_handlers_disconnect_by_func (model,g_signal_handlers_disconnect_matched ((model), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (on_begin_refresh), (tree_view))
713 on_begin_refresh,g_signal_handlers_disconnect_matched ((model), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (on_begin_refresh), (tree_view))
714 tree_view)g_signal_handlers_disconnect_matched ((model), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (on_begin_refresh), (tree_view))
;
715
716 g_signal_handlers_disconnect_by_func (model,g_signal_handlers_disconnect_matched ((model), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (on_end_refresh), (tree_view))
717 on_end_refresh,g_signal_handlers_disconnect_matched ((model), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (on_end_refresh), (tree_view))
718 tree_view)g_signal_handlers_disconnect_matched ((model), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (on_end_refresh), (tree_view))
;
719
720 g_signal_handlers_disconnect_by_func (model,g_signal_handlers_disconnect_matched ((model), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (on_unload), (tree_view))
721 on_unload,g_signal_handlers_disconnect_matched ((model), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (on_unload), (tree_view))
722 tree_view)g_signal_handlers_disconnect_matched ((model), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (on_unload), (tree_view))
;
723
724 g_signal_handlers_disconnect_by_func (model,g_signal_handlers_disconnect_matched ((model), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (on_row_inserted), (tree_view))
725 on_row_inserted,g_signal_handlers_disconnect_matched ((model), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (on_row_inserted), (tree_view))
726 tree_view)g_signal_handlers_disconnect_matched ((model), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (on_row_inserted), (tree_view))
;
727}
728
729static void
730install_restore_signals (PlumaFileBrowserView * tree_view,
731 GtkTreeModel * model)
732{
733 g_signal_connect (model,g_signal_connect_data ((model), ("begin-refresh"), (((GCallback
) (on_begin_refresh))), (tree_view), ((void*)0), (GConnectFlags
) 0)
734 "begin-refresh",g_signal_connect_data ((model), ("begin-refresh"), (((GCallback
) (on_begin_refresh))), (tree_view), ((void*)0), (GConnectFlags
) 0)
735 G_CALLBACK (on_begin_refresh),g_signal_connect_data ((model), ("begin-refresh"), (((GCallback
) (on_begin_refresh))), (tree_view), ((void*)0), (GConnectFlags
) 0)
736 tree_view)g_signal_connect_data ((model), ("begin-refresh"), (((GCallback
) (on_begin_refresh))), (tree_view), ((void*)0), (GConnectFlags
) 0)
;
737
738 g_signal_connect (model,g_signal_connect_data ((model), ("end-refresh"), (((GCallback
) (on_end_refresh))), (tree_view), ((void*)0), (GConnectFlags
) 0)
739 "end-refresh",g_signal_connect_data ((model), ("end-refresh"), (((GCallback
) (on_end_refresh))), (tree_view), ((void*)0), (GConnectFlags
) 0)
740 G_CALLBACK (on_end_refresh),g_signal_connect_data ((model), ("end-refresh"), (((GCallback
) (on_end_refresh))), (tree_view), ((void*)0), (GConnectFlags
) 0)
741 tree_view)g_signal_connect_data ((model), ("end-refresh"), (((GCallback
) (on_end_refresh))), (tree_view), ((void*)0), (GConnectFlags
) 0)
;
742
743 g_signal_connect (model,g_signal_connect_data ((model), ("unload"), (((GCallback) (on_unload
))), (tree_view), ((void*)0), (GConnectFlags) 0)
744 "unload",g_signal_connect_data ((model), ("unload"), (((GCallback) (on_unload
))), (tree_view), ((void*)0), (GConnectFlags) 0)
745 G_CALLBACK (on_unload),g_signal_connect_data ((model), ("unload"), (((GCallback) (on_unload
))), (tree_view), ((void*)0), (GConnectFlags) 0)
746 tree_view)g_signal_connect_data ((model), ("unload"), (((GCallback) (on_unload
))), (tree_view), ((void*)0), (GConnectFlags) 0)
;
747
748 g_signal_connect_after (model,g_signal_connect_data ((model), ("row-inserted"), (((GCallback
) (on_row_inserted))), (tree_view), ((void*)0), G_CONNECT_AFTER
)
749 "row-inserted",g_signal_connect_data ((model), ("row-inserted"), (((GCallback
) (on_row_inserted))), (tree_view), ((void*)0), G_CONNECT_AFTER
)
750 G_CALLBACK (on_row_inserted),g_signal_connect_data ((model), ("row-inserted"), (((GCallback
) (on_row_inserted))), (tree_view), ((void*)0), G_CONNECT_AFTER
)
751 tree_view)g_signal_connect_data ((model), ("row-inserted"), (((GCallback
) (on_row_inserted))), (tree_view), ((void*)0), G_CONNECT_AFTER
)
;
752}
753
754static void
755set_restore_expand_state (PlumaFileBrowserView * view,
756 gboolean state)
757{
758 if (state == view->priv->restore_expand_state)
759 return;
760
761 if (view->priv->expand_state)
762 {
763 g_hash_table_destroy (view->priv->expand_state);
764 view->priv->expand_state = NULL((void*)0);
765 }
766
767 if (state)
768 {
769 view->priv->expand_state = g_hash_table_new_full (g_file_hash,
770 (GEqualFunc)g_file_equal,
771 g_object_unref,
772 NULL((void*)0));
773
774 if (view->priv->model && PLUMA_IS_FILE_BROWSER_STORE (view->priv->model)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(view->priv->model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
775 {
776 fill_expand_state (view, NULL((void*)0));
777
778 install_restore_signals (view, view->priv->model);
779 }
780 }
781 else if (view->priv->model && PLUMA_IS_FILE_BROWSER_STORE (view->priv->model)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(view->priv->model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
782 {
783 uninstall_restore_signals (view, view->priv->model);
784 }
785
786 view->priv->restore_expand_state = state;
787}
788
789static void
790get_property (GObject *object,
791 guint prop_id,
792 GValue *value,
793 GParamSpec *pspec)
794{
795 PlumaFileBrowserView *obj = PLUMA_FILE_BROWSER_VIEW (object)((((PlumaFileBrowserView*) (void *) ((object)))));
796
797 switch (prop_id)
798 {
799 case PROP_CLICK_POLICY:
800 g_value_set_enum (value, obj->priv->click_policy);
801 break;
802 case PROP_RESTORE_EXPAND_STATE:
803 g_value_set_boolean (value, obj->priv->restore_expand_state);
804 break;
805 default:
806 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "pluma-file-browser-view.c", 806, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
807 break;
808 }
809}
810
811static void
812set_property (GObject *object,
813 guint prop_id,
814 const GValue *value,
815 GParamSpec *pspec)
816{
817 PlumaFileBrowserView *obj = PLUMA_FILE_BROWSER_VIEW (object)((((PlumaFileBrowserView*) (void *) ((object)))));
818
819 switch (prop_id)
820 {
821 case PROP_CLICK_POLICY:
822 set_click_policy_property (obj, g_value_get_enum (value));
823 break;
824 case PROP_RESTORE_EXPAND_STATE:
825 set_restore_expand_state (obj, g_value_get_boolean (value));
826 break;
827 default:
828 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "pluma-file-browser-view.c", 828, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
829 break;
830 }
831}
832
833static void
834pluma_file_browser_view_class_init (PlumaFileBrowserViewClass * klass)
835{
836 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) ((klass)))));
837 GtkTreeViewClass *tree_view_class = GTK_TREE_VIEW_CLASS (klass)((((GtkTreeViewClass*) (void *) ((klass)))));
838 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass)((((GtkWidgetClass*) (void *) ((klass)))));
839
840 object_class->finalize = pluma_file_browser_view_finalize;
841 object_class->get_property = get_property;
842 object_class->set_property = set_property;
843
844 /* Event handlers */
845 widget_class->motion_notify_event = motion_notify_event;
846 widget_class->enter_notify_event = enter_notify_event;
847 widget_class->leave_notify_event = leave_notify_event;
848 widget_class->button_press_event = button_press_event;
849 widget_class->button_release_event = button_release_event;
850 widget_class->drag_begin = drag_begin;
851 widget_class->key_press_event = key_press_event;
852
853 /* Tree view handlers */
854 tree_view_class->row_expanded = row_expanded;
855 tree_view_class->row_collapsed = row_collapsed;
856
857 /* Default handlers */
858 klass->directory_activated = directory_activated;
859
860 g_object_class_install_property (object_class, PROP_CLICK_POLICY,
861 g_param_spec_enum ("click-policy",
862 "Click Policy",
863 "The click policy",
864 PLUMA_TYPE_FILE_BROWSER_VIEW_CLICK_POLICY(pluma_file_browser_view_click_policy_get_type()),
865 PLUMA_FILE_BROWSER_VIEW_CLICK_POLICY_DOUBLE,
866 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
867
868 g_object_class_install_property (object_class, PROP_RESTORE_EXPAND_STATE,
869 g_param_spec_boolean ("restore-expand-state",
870 "Restore Expand State",
871 "Restore expanded state of loaded directories",
872 FALSE(0),
873 G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
874
875 signals[ERROR] =
876 g_signal_new ("error",
877 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
878 G_SIGNAL_RUN_LAST,
879 G_STRUCT_OFFSET (PlumaFileBrowserViewClass, error)((glong) __builtin_offsetof(PlumaFileBrowserViewClass, error)
)
,
880 NULL((void*)0), NULL((void*)0), NULL((void*)0),
881 G_TYPE_NONE((GType) ((1) << (2))), 2, G_TYPE_UINT((GType) ((7) << (2))), G_TYPE_STRING((GType) ((16) << (2))));
882 signals[FILE_ACTIVATED] =
883 g_signal_new ("file-activated",
884 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
885 G_SIGNAL_RUN_LAST,
886 G_STRUCT_OFFSET (PlumaFileBrowserViewClass, file_activated)((glong) __builtin_offsetof(PlumaFileBrowserViewClass, file_activated
))
,
887 NULL((void*)0), NULL((void*)0), NULL((void*)0),
888 G_TYPE_NONE((GType) ((1) << (2))), 1, GTK_TYPE_TREE_ITER(gtk_tree_iter_get_type ()));
889 signals[DIRECTORY_ACTIVATED] =
890 g_signal_new ("directory-activated",
891 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
892 G_SIGNAL_RUN_LAST,
893 G_STRUCT_OFFSET (PlumaFileBrowserViewClass, directory_activated)((glong) __builtin_offsetof(PlumaFileBrowserViewClass, directory_activated
))
,
894 NULL((void*)0), NULL((void*)0), NULL((void*)0),
895 G_TYPE_NONE((GType) ((1) << (2))), 1, GTK_TYPE_TREE_ITER(gtk_tree_iter_get_type ()));
896 signals[BOOKMARK_ACTIVATED] =
897 g_signal_new ("bookmark-activated",
898 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
899 G_SIGNAL_RUN_LAST,
900 G_STRUCT_OFFSET (PlumaFileBrowserViewClass, bookmark_activated)((glong) __builtin_offsetof(PlumaFileBrowserViewClass, bookmark_activated
))
,
901 NULL((void*)0), NULL((void*)0), NULL((void*)0),
902 G_TYPE_NONE((GType) ((1) << (2))), 1, GTK_TYPE_TREE_ITER(gtk_tree_iter_get_type ()));
903}
904
905static void
906pluma_file_browser_view_class_finalize (PlumaFileBrowserViewClass *klass)
907{
908 /* dummy function - used by G_DEFINE_DYNAMIC_TYPE_EXTENDED */
909}
910
911static void
912cell_data_cb (GtkTreeViewColumn * tree_column, GtkCellRenderer * cell,
913 GtkTreeModel * tree_model, GtkTreeIter * iter,
914 PlumaFileBrowserView * obj)
915{
916 GtkTreePath *path;
917 PangoUnderline underline = PANGO_UNDERLINE_NONE;
918 gboolean editable = FALSE(0);
919
920 path = gtk_tree_model_get_path (tree_model, iter);
921
922 if (obj->priv->click_policy == PLUMA_FILE_BROWSER_VIEW_CLICK_POLICY_SINGLE) {
923 if (obj->priv->hover_path != NULL((void*)0) &&
924 gtk_tree_path_compare (path, obj->priv->hover_path) == 0)
925 underline = PANGO_UNDERLINE_SINGLE;
926 }
927
928 if (PLUMA_IS_FILE_BROWSER_STORE (tree_model)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
929 {
930 if (obj->priv->editable != NULL((void*)0) &&
931 gtk_tree_row_reference_valid (obj->priv->editable))
932 {
933 GtkTreePath *edpath = gtk_tree_row_reference_get_path (obj->priv->editable);
934
935 editable = edpath && gtk_tree_path_compare (path, edpath) == 0;
936 }
937 }
938
939 gtk_tree_path_free (path);
940 g_object_set (cell, "editable", editable, "underline", underline, NULL((void*)0));
941}
942
943static void
944pluma_file_browser_view_init (PlumaFileBrowserView * obj)
945{
946 GdkDisplay *display;
947
948 obj->priv = pluma_file_browser_view_get_instance_private (obj);
949
950 obj->priv->column = gtk_tree_view_column_new ();
951
952 obj->priv->pixbuf_renderer = gtk_cell_renderer_pixbuf_new ();
953 gtk_tree_view_column_pack_start (obj->priv->column,
954 obj->priv->pixbuf_renderer,
955 FALSE(0));
956 gtk_tree_view_column_add_attribute (obj->priv->column,
957 obj->priv->pixbuf_renderer,
958 "pixbuf",
959 PLUMA_FILE_BROWSER_STORE_COLUMN_ICON);
960
961 obj->priv->text_renderer = gtk_cell_renderer_text_new ();
962 gtk_tree_view_column_pack_start (obj->priv->column,
963 obj->priv->text_renderer, TRUE(!(0)));
964 gtk_tree_view_column_add_attribute (obj->priv->column,
965 obj->priv->text_renderer,
966 "text",
967 PLUMA_FILE_BROWSER_STORE_COLUMN_NAME);
968
969 g_signal_connect (obj->priv->text_renderer, "edited",g_signal_connect_data ((obj->priv->text_renderer), ("edited"
), (((GCallback) (on_cell_edited))), (obj), ((void*)0), (GConnectFlags
) 0)
970 G_CALLBACK (on_cell_edited), obj)g_signal_connect_data ((obj->priv->text_renderer), ("edited"
), (((GCallback) (on_cell_edited))), (obj), ((void*)0), (GConnectFlags
) 0)
;
971
972 gtk_tree_view_append_column (GTK_TREE_VIEW (obj)((((GtkTreeView*) (void *) ((obj))))),
973 obj->priv->column);
974 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (obj)((((GtkTreeView*) (void *) ((obj))))), FALSE(0));
975
976 gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (obj)((((GtkTreeView*) (void *) ((obj))))),
977 GDK_BUTTON1_MASK,
978 drag_source_targets,
979 G_N_ELEMENTS (drag_source_targets)(sizeof (drag_source_targets) / sizeof ((drag_source_targets)
[0]))
,
980 GDK_ACTION_COPY);
981
982 display = gtk_widget_get_display (GTK_WIDGET (obj)((((GtkWidget*) (void *) ((obj))))));
983 obj->priv->busy_cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
984}
985
986static gboolean
987bookmarks_separator_func (GtkTreeModel * model, GtkTreeIter * iter,
988 gpointer user_data)
989{
990 guint flags;
991
992 gtk_tree_model_get (model, iter,
993 PLUMA_FILE_BOOKMARKS_STORE_COLUMN_FLAGS,
994 &flags, -1);
995
996 return (flags & PLUMA_FILE_BOOKMARKS_STORE_IS_SEPARATOR);
997}
998
999/* Public */
1000GtkWidget *
1001pluma_file_browser_view_new (void)
1002{
1003 PlumaFileBrowserView *obj =
1004 PLUMA_FILE_BROWSER_VIEW (g_object_new((((PlumaFileBrowserView*) (void *) ((g_object_new ((pluma_file_browser_view_get_type
()), ((void*)0)))))))
1005 (PLUMA_TYPE_FILE_BROWSER_VIEW, NULL))((((PlumaFileBrowserView*) (void *) ((g_object_new ((pluma_file_browser_view_get_type
()), ((void*)0)))))))
;
1006
1007 return GTK_WIDGET (obj)((((GtkWidget*) (void *) ((obj)))));
1008}
1009
1010void
1011pluma_file_browser_view_set_model (PlumaFileBrowserView * tree_view,
1012 GtkTreeModel * model)
1013{
1014 GtkTreeSelection *selection;
1015
1016 if (tree_view->priv->model == model)
1017 return;
1018
1019 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)((((GtkTreeView*) (void *) ((tree_view))))));
1020
1021 if (PLUMA_IS_FILE_BOOKMARKS_STORE (model)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(model)); GType __t = ((pluma_file_bookmarks_store_get_type (
))); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
) {
1022 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
1023 gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW((((GtkTreeView*) (void *) ((tree_view)))))
1024 (tree_view)((((GtkTreeView*) (void *) ((tree_view))))),
1025 bookmarks_separator_func,
1026 NULL((void*)0), NULL((void*)0));
1027 gtk_tree_view_column_set_cell_data_func (tree_view->priv->
1028 column,
1029 tree_view->priv->
1030 text_renderer,
1031 (GtkTreeCellDataFunc)
1032 cell_data_cb,
1033 tree_view, NULL((void*)0));
1034 } else {
1035 gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
1036 gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW((((GtkTreeView*) (void *) ((tree_view)))))
1037 (tree_view)((((GtkTreeView*) (void *) ((tree_view))))), NULL((void*)0),
1038 NULL((void*)0), NULL((void*)0));
1039 gtk_tree_view_column_set_cell_data_func (tree_view->priv->
1040 column,
1041 tree_view->priv->
1042 text_renderer,
1043 (GtkTreeCellDataFunc)
1044 cell_data_cb,
1045 tree_view, NULL((void*)0));
1046
1047 if (tree_view->priv->restore_expand_state)
1048 install_restore_signals (tree_view, model);
1049
1050 }
1051
1052 if (tree_view->priv->hover_path != NULL((void*)0)) {
1053 gtk_tree_path_free (tree_view->priv->hover_path);
1054 tree_view->priv->hover_path = NULL((void*)0);
1055 }
1056
1057 if (PLUMA_IS_FILE_BROWSER_STORE (tree_view->priv->model)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(tree_view->priv->model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
) {
1058 if (tree_view->priv->restore_expand_state)
1059 uninstall_restore_signals (tree_view,
1060 tree_view->priv->model);
1061 }
1062
1063 tree_view->priv->model = model;
1064 gtk_tree_view_set_model (GTK_TREE_VIEW (tree_view)((((GtkTreeView*) (void *) ((tree_view))))), model);
1065}
1066
1067void
1068pluma_file_browser_view_start_rename (PlumaFileBrowserView * tree_view,
1069 GtkTreeIter * iter)
1070{
1071 guint flags;
1072 GtkTreeRowReference *rowref;
1073 GtkTreePath *path;
1074
1075 g_return_if_fail (PLUMA_IS_FILE_BROWSER_VIEW (tree_view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_15
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((pluma_file_browser_view_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_15 = 1; else _g_boolean_var_15 = 0
; _g_boolean_var_15; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_VIEW (tree_view)"
); return; } } while (0)
;
1076 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STOREdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_16
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view->priv->model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_16 = 1; else _g_boolean_var_16 = 0
; _g_boolean_var_16; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_view->priv->model)"
); return; } } while (0)
1077 (tree_view->priv->model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_16
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view->priv->model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_16 = 1; else _g_boolean_var_16 = 0
; _g_boolean_var_16; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_view->priv->model)"
); return; } } while (0)
;
1078 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_17
; if (iter != ((void*)0)) _g_boolean_var_17 = 1; else _g_boolean_var_17
= 0; _g_boolean_var_17; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
1079
1080 gtk_tree_model_get (tree_view->priv->model, iter,
1081 PLUMA_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
1082 -1);
1083
1084 if (!(FILE_IS_DIR (flags)(flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY) || !FILE_IS_DUMMY (flags)(flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY)))
1085 return;
1086
1087 path = gtk_tree_model_get_path (tree_view->priv->model, iter);
1088 rowref = gtk_tree_row_reference_new (tree_view->priv->model, path);
1089
1090 /* Start editing */
1091 gtk_widget_grab_focus (GTK_WIDGET (tree_view)((((GtkWidget*) (void *) ((tree_view))))));
1092
1093 if (gtk_tree_path_up (path))
1094 gtk_tree_view_expand_to_path (GTK_TREE_VIEW (tree_view)((((GtkTreeView*) (void *) ((tree_view))))),
1095 path);
1096
1097 gtk_tree_path_free (path);
1098 tree_view->priv->editable = rowref;
1099
1100 gtk_tree_view_set_cursor (GTK_TREE_VIEW (tree_view)((((GtkTreeView*) (void *) ((tree_view))))),
1101 gtk_tree_row_reference_get_path (tree_view->priv->editable),
1102 tree_view->priv->column, TRUE(!(0)));
1103
1104 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (tree_view)((((GtkTreeView*) (void *) ((tree_view))))),
1105 gtk_tree_row_reference_get_path (tree_view->priv->editable),
1106 tree_view->priv->column,
1107 FALSE(0), 0.0, 0.0);
1108}
1109
1110void
1111pluma_file_browser_view_set_click_policy (PlumaFileBrowserView *tree_view,
1112 PlumaFileBrowserViewClickPolicy policy)
1113{
1114 g_return_if_fail (PLUMA_IS_FILE_BROWSER_VIEW (tree_view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_18
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((pluma_file_browser_view_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_18 = 1; else _g_boolean_var_18 = 0
; _g_boolean_var_18; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_VIEW (tree_view)"
); return; } } while (0)
;
1115
1116 set_click_policy_property (tree_view, policy);
1117
1118 g_object_notify (G_OBJECT (tree_view)((((GObject*) (void *) ((tree_view))))), "click-policy");
1119}
1120
1121void
1122pluma_file_browser_view_set_restore_expand_state (PlumaFileBrowserView * tree_view,
1123 gboolean restore_expand_state)
1124{
1125 g_return_if_fail (PLUMA_IS_FILE_BROWSER_VIEW (tree_view))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_19
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_view)); GType __t = ((pluma_file_browser_view_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_19 = 1; else _g_boolean_var_19 = 0
; _g_boolean_var_19; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_VIEW (tree_view)"
); return; } } while (0)
;
1126
1127 set_restore_expand_state (tree_view, restore_expand_state);
1128 g_object_notify (G_OBJECT (tree_view)((((GObject*) (void *) ((tree_view))))), "restore-expand-state");
1129}
1130
1131/* Signal handlers */
1132static void
1133on_cell_edited (GtkCellRendererText * cell, gchar * path, gchar * new_text,
1134 PlumaFileBrowserView * tree_view)
1135{
1136 GtkTreePath * treepath;
1137 GtkTreeIter iter;
1138 gboolean ret;
1139 GError * error = NULL((void*)0);
1140
1141 gtk_tree_row_reference_free (tree_view->priv->editable);
1142 tree_view->priv->editable = NULL((void*)0);
1143
1144 if (new_text == NULL((void*)0) || *new_text == '\0')
1145 return;
1146
1147 treepath = gtk_tree_path_new_from_string (path);
1148 ret = gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_view->priv->model)((((GtkTreeModel*) (void *) ((tree_view->priv->model)))
))
, &iter, treepath);
1149 gtk_tree_path_free (treepath);
1150
1151 if (ret) {
1152 if (pluma_file_browser_store_rename (PLUMA_FILE_BROWSER_STORE (tree_view->priv->model)((((PlumaFileBrowserStore*) (void *) ((tree_view->priv->
model)))))
,
1153 &iter, new_text, &error)) {
1154 treepath = gtk_tree_model_get_path (GTK_TREE_MODEL (tree_view->priv->model)((((GtkTreeModel*) (void *) ((tree_view->priv->model)))
))
, &iter);
1155 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (tree_view)((((GtkTreeView*) (void *) ((tree_view))))),
1156 treepath, NULL((void*)0),
1157 FALSE(0), 0.0, 0.0);
1158 gtk_tree_path_free (treepath);
1159 }
1160 else {
1161 if (error) {
1162 g_signal_emit (tree_view, signals[ERROR], 0,
1163 error->code, error->message);
1164 g_error_free (error);
1165 }
1166 }
1167 }
1168}
1169
1170static void
1171on_begin_refresh (PlumaFileBrowserStore * model,
1172 PlumaFileBrowserView * view)
1173{
1174 /* Store the refresh state, so we can handle unloading of nodes while
1175 refreshing properly */
1176 view->priv->is_refresh = TRUE(!(0));
1177}
1178
1179static void
1180on_end_refresh (PlumaFileBrowserStore * model,
1181 PlumaFileBrowserView * view)
1182{
1183 /* Store the refresh state, so we can handle unloading of nodes while
1184 refreshing properly */
1185 view->priv->is_refresh = FALSE(0);
1186}
1187
1188static void
1189on_unload (PlumaFileBrowserStore * model,
1190 gchar const * uri,
1191 PlumaFileBrowserView * view)
1192{
1193 /* Don't remove the expand state if we are refreshing */
1194 if (!view->priv->restore_expand_state || view->priv->is_refresh)
1195 return;
1196
1197 remove_expand_state (view, uri);
1198}
1199
1200static void
1201restore_expand_state (PlumaFileBrowserView * view,
1202 PlumaFileBrowserStore * model,
1203 GtkTreeIter * iter)
1204{
1205 gchar * uri;
1206 GFile * file;
1207 GtkTreePath * path;
1208
1209 gtk_tree_model_get (GTK_TREE_MODEL (model)((((GtkTreeModel*) (void *) ((model))))),
1210 iter,
1211 PLUMA_FILE_BROWSER_STORE_COLUMN_URI,
1212 &uri,
1213 -1);
1214
1215 if (!uri)
1216 return;
1217
1218 file = g_file_new_for_uri (uri);
1219 path = gtk_tree_model_get_path (GTK_TREE_MODEL (model)((((GtkTreeModel*) (void *) ((model))))), iter);
1220
1221 if (g_hash_table_lookup (view->priv->expand_state, file))
1222 {
1223 gtk_tree_view_expand_row (GTK_TREE_VIEW (view)((((GtkTreeView*) (void *) ((view))))),
1224 path,
1225 FALSE(0));
1226 }
1227
1228 gtk_tree_path_free (path);
1229
1230 g_object_unref (file);
1231 g_free (uri);
1232}
1233
1234static void
1235on_row_inserted (PlumaFileBrowserStore * model,
1236 GtkTreePath * path,
1237 GtkTreeIter * iter,
1238 PlumaFileBrowserView * view)
1239{
1240 GtkTreeIter parent;
1241 GtkTreePath * copy;
1242
1243 if (gtk_tree_model_iter_has_child (GTK_TREE_MODEL (model)((((GtkTreeModel*) (void *) ((model))))), iter))
1244 restore_expand_state (view, model, iter);
1245
1246 copy = gtk_tree_path_copy (path);
1247
1248 if (gtk_tree_path_up (copy) &&
1249 (gtk_tree_path_get_depth (copy) != 0) &&
1250 gtk_tree_model_get_iter (GTK_TREE_MODEL (model)((((GtkTreeModel*) (void *) ((model))))), &parent, copy))
1251 {
1252 restore_expand_state (view, model, &parent);
1253 }
1254
1255 gtk_tree_path_free (copy);
1256}
1257
1258void
1259_pluma_file_browser_view_register_type (GTypeModule *type_module)
1260{
1261 pluma_file_browser_view_register_type (type_module);
1262}
1263
1264// ex:ts=8:noet:
diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-13aee1.html b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-13aee1.html new file mode 100644 index 00000000..812fb079 --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-13aee1.html @@ -0,0 +1,1139 @@ + + + +pluma-document-output-stream.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:pluma/pluma-document-output-stream.c
Warning:line 332, column 26
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pluma-document-output-stream.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/pluma -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I .. -I . -I ./mate-submodules/libegg -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/gtksourceview-4 -I /usr/include/libpeas-1.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D DATADIR="/usr/local/share" -D PLUMA_DATADIR="/usr/local/share/pluma" -D PLUMA_LOCALEDIR="/usr/local/share/locale/" -D LIBDIR="/usr/local/lib" -D PLUMA_LIBDIR="/usr/local/lib/pluma" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/pluma -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-10-22-114445-13211-1 -x c pluma-document-output-stream.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * pluma-document-output-stream.c
3 * This file is part of pluma
4 *
5 * Copyright (C) 2010 - Ignacio Casal Quinteiro
6 * Copyright (C) 2012-2021 MATE Developers
7 *
8 * pluma is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * pluma is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with pluma; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301 USA
22 */
23
24#include "config.h"
25
26#include <string.h>
27#include <glib.h>
28#include <glib/gi18n.h>
29#include <gio/gio.h>
30#include "pluma-document-output-stream.h"
31
32/* NOTE: never use async methods on this stream, the stream is just
33 * a wrapper around GtkTextBuffer api so that we can use GIO Stream
34 * methods, but the undelying code operates on a GtkTextBuffer, so
35 * there is no I/O involved and should be accessed only by the main
36 * thread */
37
38#define MAX_UNICHAR_LEN6 6
39
40struct _PlumaDocumentOutputStreamPrivate
41{
42 PlumaDocument *doc;
43 GtkTextIter pos;
44
45 gchar *buffer;
46 gsize buflen;
47
48 guint is_initialized : 1;
49 guint is_closed : 1;
50};
51
52enum
53{
54 PROP_0,
55 PROP_DOCUMENT
56};
57
58G_DEFINE_TYPE_WITH_PRIVATE (PlumaDocumentOutputStream, pluma_document_output_stream, G_TYPE_OUTPUT_STREAM)static void pluma_document_output_stream_init (PlumaDocumentOutputStream
*self); static void pluma_document_output_stream_class_init (
PlumaDocumentOutputStreamClass *klass); static GType pluma_document_output_stream_get_type_once
(void); static gpointer pluma_document_output_stream_parent_class
= ((void*)0); static gint PlumaDocumentOutputStream_private_offset
; static void pluma_document_output_stream_class_intern_init (
gpointer klass) { pluma_document_output_stream_parent_class =
g_type_class_peek_parent (klass); if (PlumaDocumentOutputStream_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &PlumaDocumentOutputStream_private_offset
); pluma_document_output_stream_class_init ((PlumaDocumentOutputStreamClass
*) klass); } __attribute__ ((__unused__)) static inline gpointer
pluma_document_output_stream_get_instance_private (PlumaDocumentOutputStream
*self) { return (((gpointer) ((guint8*) (self) + (glong) (PlumaDocumentOutputStream_private_offset
)))); } GType pluma_document_output_stream_get_type (void) { static
gsize static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); (void) (0 ? (gpointer) *(
&static_g_define_type_id) : ((void*)0)); (!(__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id
)); }))) { GType g_define_type_id = pluma_document_output_stream_get_type_once
(); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&static_g_define_type_id) = (g_define_type_id)
) : (void) 0; g_once_init_leave ((&static_g_define_type_id
), (gsize) (g_define_type_id)); })); } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType pluma_document_output_stream_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((g_output_stream_get_type ()), g_intern_static_string ("PlumaDocumentOutputStream"
), sizeof (PlumaDocumentOutputStreamClass), (GClassInitFunc)(
void (*)(void)) pluma_document_output_stream_class_intern_init
, sizeof (PlumaDocumentOutputStream), (GInstanceInitFunc)(void
(*)(void)) pluma_document_output_stream_init, (GTypeFlags) 0
); { {{ PlumaDocumentOutputStream_private_offset = g_type_add_instance_private
(g_define_type_id, sizeof (PlumaDocumentOutputStreamPrivate)
); };} } return g_define_type_id; }
59
60static gssize pluma_document_output_stream_write (GOutputStream *stream,
61 const void *buffer,
62 gsize count,
63 GCancellable *cancellable,
64 GError **error);
65
66static gboolean pluma_document_output_stream_flush (GOutputStream *stream,
67 GCancellable *cancellable,
68 GError **error);
69
70static gboolean pluma_document_output_stream_close (GOutputStream *stream,
71 GCancellable *cancellable,
72 GError **error);
73
74static void
75pluma_document_output_stream_set_property (GObject *object,
76 guint prop_id,
77 const GValue *value,
78 GParamSpec *pspec)
79{
80 PlumaDocumentOutputStream *stream = PLUMA_DOCUMENT_OUTPUT_STREAM (object)((((PlumaDocumentOutputStream*) (void *) ((object)))));
81
82 switch (prop_id)
83 {
84 case PROP_DOCUMENT:
85 stream->priv->doc = PLUMA_DOCUMENT (g_value_get_object (value))((((PlumaDocument*) (void *) ((g_value_get_object (value)))))
)
;
86 break;
87
88 default:
89 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "pluma-document-output-stream.c", 89, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
90 break;
91 }
92}
93
94static void
95pluma_document_output_stream_get_property (GObject *object,
96 guint prop_id,
97 GValue *value,
98 GParamSpec *pspec)
99{
100 PlumaDocumentOutputStream *stream = PLUMA_DOCUMENT_OUTPUT_STREAM (object)((((PlumaDocumentOutputStream*) (void *) ((object)))));
101
102 switch (prop_id)
103 {
104 case PROP_DOCUMENT:
105 g_value_set_object (value, stream->priv->doc);
106 break;
107
108 default:
109 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "pluma-document-output-stream.c", 109, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
110 break;
111 }
112}
113
114static void
115pluma_document_output_stream_finalize (GObject *object)
116{
117 PlumaDocumentOutputStream *stream = PLUMA_DOCUMENT_OUTPUT_STREAM (object)((((PlumaDocumentOutputStream*) (void *) ((object)))));
118
119 g_free (stream->priv->buffer);
120
121 G_OBJECT_CLASS (pluma_document_output_stream_parent_class)((((GObjectClass*) (void *) ((pluma_document_output_stream_parent_class
)))))
->finalize (object);
122}
123
124static void
125pluma_document_output_stream_constructed (GObject *object)
126{
127 PlumaDocumentOutputStream *stream = PLUMA_DOCUMENT_OUTPUT_STREAM (object)((((PlumaDocumentOutputStream*) (void *) ((object)))));
128
129 if (!stream->priv->doc)
130 {
131 g_critical ("This should never happen, a problem happened constructing the Document Output Stream!");
132 return;
133 }
134
135 /* Init the undoable action */
136 gtk_source_buffer_begin_not_undoable_action (GTK_SOURCE_BUFFER (stream->priv->doc)((((GtkSourceBuffer*) (void *) ((stream->priv->doc))))));
137 /* clear the buffer */
138 gtk_text_buffer_set_text (GTK_TEXT_BUFFER (stream->priv->doc)((((GtkTextBuffer*) (void *) ((stream->priv->doc))))),
139 "", 0);
140 gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (stream->priv->doc)((((GtkTextBuffer*) (void *) ((stream->priv->doc))))),
141 FALSE(0));
142
143 gtk_source_buffer_end_not_undoable_action (GTK_SOURCE_BUFFER (stream->priv->doc)((((GtkSourceBuffer*) (void *) ((stream->priv->doc))))));
144}
145
146static void
147pluma_document_output_stream_class_init (PlumaDocumentOutputStreamClass *klass)
148{
149 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) ((klass)))));
150 GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass)((((GOutputStreamClass*) (void *) ((klass)))));
151
152 object_class->get_property = pluma_document_output_stream_get_property;
153 object_class->set_property = pluma_document_output_stream_set_property;
154 object_class->finalize = pluma_document_output_stream_finalize;
155 object_class->constructed = pluma_document_output_stream_constructed;
156
157 stream_class->write_fn = pluma_document_output_stream_write;
158 stream_class->flush = pluma_document_output_stream_flush;
159 stream_class->close_fn = pluma_document_output_stream_close;
160
161 g_object_class_install_property (object_class,
162 PROP_DOCUMENT,
163 g_param_spec_object ("document",
164 "Document",
165 "The document which is written",
166 PLUMA_TYPE_DOCUMENT(pluma_document_get_type()),
167 G_PARAM_READWRITE |
168 G_PARAM_CONSTRUCT_ONLY));
169}
170
171static void
172pluma_document_output_stream_init (PlumaDocumentOutputStream *stream)
173{
174 stream->priv = pluma_document_output_stream_get_instance_private (stream);
175
176 stream->priv->buffer = NULL((void*)0);
177 stream->priv->buflen = 0;
178
179 stream->priv->is_initialized = FALSE(0);
180 stream->priv->is_closed = FALSE(0);
181}
182
183static PlumaDocumentNewlineType
184get_newline_type (GtkTextIter *end)
185{
186 PlumaDocumentNewlineType res;
187 GtkTextIter copy;
188 gunichar c;
189
190 copy = *end;
191 c = gtk_text_iter_get_char (&copy);
192
193 if (g_unichar_break_type (c) == G_UNICODE_BREAK_CARRIAGE_RETURN)
194 {
195 if (gtk_text_iter_forward_char (&copy) &&
196 g_unichar_break_type (gtk_text_iter_get_char (&copy)) == G_UNICODE_BREAK_LINE_FEED)
197 {
198 res = PLUMA_DOCUMENT_NEWLINE_TYPE_CR_LF;
199 }
200 else
201 {
202 res = PLUMA_DOCUMENT_NEWLINE_TYPE_CR;
203 }
204 }
205 else
206 {
207 res = PLUMA_DOCUMENT_NEWLINE_TYPE_LF;
208 }
209
210 return res;
211}
212
213GOutputStream *
214pluma_document_output_stream_new (PlumaDocument *doc)
215{
216 return G_OUTPUT_STREAM (g_object_new (PLUMA_TYPE_DOCUMENT_OUTPUT_STREAM,((((GOutputStream*) (void *) ((g_object_new ((pluma_document_output_stream_get_type
()), "document", doc, ((void*)0)))))))
217 "document", doc, NULL))((((GOutputStream*) (void *) ((g_object_new ((pluma_document_output_stream_get_type
()), "document", doc, ((void*)0)))))))
;
218}
219
220PlumaDocumentNewlineType
221pluma_document_output_stream_detect_newline_type (PlumaDocumentOutputStream *stream)
222{
223 PlumaDocumentNewlineType type;
224 GtkTextIter iter;
225
226 g_return_val_if_fail (PLUMA_IS_DOCUMENT_OUTPUT_STREAM (stream),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_11
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stream)); GType __t = ((pluma_document_output_stream_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_11 = 1; else _g_boolean_var_11 = 0
; _g_boolean_var_11; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_DOCUMENT_OUTPUT_STREAM (stream)"
); return (PLUMA_DOCUMENT_NEWLINE_TYPE_LF); } } while (0)
227 PLUMA_DOCUMENT_NEWLINE_TYPE_DEFAULT)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_11
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((stream)); GType __t = ((pluma_document_output_stream_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_11 = 1; else _g_boolean_var_11 = 0
; _g_boolean_var_11; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_DOCUMENT_OUTPUT_STREAM (stream)"
); return (PLUMA_DOCUMENT_NEWLINE_TYPE_LF); } } while (0)
;
228
229 type = PLUMA_DOCUMENT_NEWLINE_TYPE_DEFAULTPLUMA_DOCUMENT_NEWLINE_TYPE_LF;
230
231 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (stream->priv->doc)((((GtkTextBuffer*) (void *) ((stream->priv->doc))))),
232 &iter);
233
234 if (gtk_text_iter_ends_line (&iter) || gtk_text_iter_forward_to_line_end (&iter))
235 {
236 type = get_newline_type (&iter);
237 }
238
239 return type;
240}
241
242/* If the last char is a newline, remove it from the buffer (otherwise
243 GtkTextView shows it as an empty line). See bug #324942. */
244static void
245remove_ending_newline (PlumaDocumentOutputStream *stream)
246{
247 GtkTextIter end;
248 GtkTextIter start;
249
250 gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (stream->priv->doc)((((GtkTextBuffer*) (void *) ((stream->priv->doc))))), &end);
251 start = end;
252
253 gtk_text_iter_set_line_offset (&start, 0);
254
255 if (gtk_text_iter_ends_line (&start) &&
256 gtk_text_iter_backward_line (&start))
257 {
258 if (!gtk_text_iter_ends_line (&start))
259 {
260 gtk_text_iter_forward_to_line_end (&start);
261 }
262
263 /* Delete the empty line which is from 'start' to 'end' */
264 gtk_text_buffer_delete (GTK_TEXT_BUFFER (stream->priv->doc)((((GtkTextBuffer*) (void *) ((stream->priv->doc))))),
265 &start,
266 &end);
267 }
268}
269
270static void
271end_append_text_to_document (PlumaDocumentOutputStream *stream)
272{
273 remove_ending_newline (stream);
274
275 gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (stream->priv->doc)((((GtkTextBuffer*) (void *) ((stream->priv->doc))))),
276 FALSE(0));
277
278 gtk_source_buffer_end_not_undoable_action (GTK_SOURCE_BUFFER (stream->priv->doc)((((GtkSourceBuffer*) (void *) ((stream->priv->doc))))));
279}
280
281static gssize
282pluma_document_output_stream_write (GOutputStream *stream,
283 const void *buffer,
284 gsize count,
285 GCancellable *cancellable,
286 GError **error)
287{
288 PlumaDocumentOutputStream *ostream;
289 gchar *text;
290 gsize len;
291 gboolean freetext = FALSE(0);
292 const gchar *end;
293 gboolean valid;
294
295 if (g_cancellable_set_error_if_cancelled (cancellable, error))
5
Assuming the condition is false
6
Taking false branch
296 return -1;
297
298 ostream = PLUMA_DOCUMENT_OUTPUT_STREAM (stream)((((PlumaDocumentOutputStream*) (void *) ((stream)))));
299
300 if (!ostream->priv->is_initialized
6.1
Field 'is_initialized' is not equal to 0
)
7
Taking false branch
301 {
302 /* Init the undoable action */
303 gtk_source_buffer_begin_not_undoable_action (GTK_SOURCE_BUFFER (ostream->priv->doc)((((GtkSourceBuffer*) (void *) ((ostream->priv->doc))))
)
);
304
305 gtk_text_buffer_get_start_iter (GTK_TEXT_BUFFER (ostream->priv->doc)((((GtkTextBuffer*) (void *) ((ostream->priv->doc))))),
306 &ostream->priv->pos);
307 ostream->priv->is_initialized = TRUE(!(0));
308 }
309
310 if (ostream->priv->buflen
7.1
Field 'buflen' is > 0
> 0)
8
Taking true branch
311 {
312 len = ostream->priv->buflen + count;
313 text = g_new (gchar , len + 1)(gchar *) (__extension__ ({ gsize __n = (gsize) (len + 1); gsize
__s = sizeof (gchar); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
9
Taking true branch
314 memcpy (text, ostream->priv->buffer, ostream->priv->buflen);
315 memcpy (text + ostream->priv->buflen, buffer, count);
316 text[len] = '\0';
317 g_free (ostream->priv->buffer);
318 ostream->priv->buffer = NULL((void*)0);
319 ostream->priv->buflen = 0;
320 freetext = TRUE(!(0));
321 }
322 else
323 {
324 text = (gchar *) buffer;
325 len = count;
326 }
327
328 /* validate */
329 valid = g_utf8_validate (text, len, &end);
330
331 /* Avoid keeping a CRLF across two buffers. */
332 if (valid && len > 1 && end[-1] == '\r')
10
Assuming 'valid' is not equal to 0
11
Assuming 'len' is > 1
12
Out of bound memory access (access exceeds upper limit of memory block)
333 {
334 valid = FALSE(0);
335 end--;
336 }
337
338 if (!valid)
339 {
340 gsize nvalid = end - text;
341 gsize remainder = len - nvalid;
342 gunichar ch;
343
344 if ((remainder < MAX_UNICHAR_LEN6) &&
345 ((ch = g_utf8_get_char_validated (text + nvalid, remainder)) == (gunichar)-2 ||
346 ch == (gunichar)'\r'))
347 {
348 ostream->priv->buffer = g_strndup (end, remainder);
349 ostream->priv->buflen = remainder;
350 len -= remainder;
351 }
352 else
353 {
354 /* TODO: we could escape invalid text and tag it in red
355 * and make the doc readonly.
356 */
357 g_set_error (error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_DATA,
358 _("Invalid UTF-8 sequence in input")dcgettext (((void*)0), "Invalid UTF-8 sequence in input", 5));
359
360 if (freetext)
361 g_free (text);
362
363 return -1;
364 }
365 }
366
367 gtk_text_buffer_insert (GTK_TEXT_BUFFER (ostream->priv->doc)((((GtkTextBuffer*) (void *) ((ostream->priv->doc))))),
368 &ostream->priv->pos, text, len);
369
370 if (freetext)
371 g_free (text);
372
373 return count;
374}
375
376static gboolean
377pluma_document_output_stream_flush (GOutputStream *stream,
378 GCancellable *cancellable,
379 GError **error)
380{
381 PlumaDocumentOutputStream *ostream = PLUMA_DOCUMENT_OUTPUT_STREAM (stream)((((PlumaDocumentOutputStream*) (void *) ((stream)))));
382
383 /* Flush deferred data if some. */
384 if (!ostream->priv->is_closed && ostream->priv->is_initialized &&
1
Assuming field 'is_closed' is 0
2
Assuming field 'is_initialized' is not equal to 0
385 ostream->priv->buflen > 0 &&
3
Assuming field 'buflen' is > 0
386 pluma_document_output_stream_write (stream, "", 0, cancellable,
4
Calling 'pluma_document_output_stream_write'
387 error) == -1)
388 return FALSE(0);
389
390 return TRUE(!(0));
391}
392
393static gboolean
394pluma_document_output_stream_close (GOutputStream *stream,
395 GCancellable *cancellable,
396 GError **error)
397{
398 PlumaDocumentOutputStream *ostream = PLUMA_DOCUMENT_OUTPUT_STREAM (stream)((((PlumaDocumentOutputStream*) (void *) ((stream)))));
399
400 if (!ostream->priv->is_closed && ostream->priv->is_initialized)
401 {
402 end_append_text_to_document (ostream);
403 ostream->priv->is_closed = TRUE(!(0));
404 }
405
406 if (ostream->priv->buflen > 0)
407 {
408 g_set_error (error, G_IO_ERRORg_io_error_quark(), G_IO_ERROR_INVALID_DATA,
409 _("Incomplete UTF-8 sequence in input")dcgettext (((void*)0), "Incomplete UTF-8 sequence in input", 5
)
);
410 return FALSE(0);
411 }
412
413 return TRUE(!(0));
414}
diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-1e519c.html b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-1e519c.html new file mode 100644 index 00000000..249b1d8a --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-1e519c.html @@ -0,0 +1,1475 @@ + + + +pluma-taglist-plugin-panel.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:plugins/taglist/pluma-taglist-plugin-panel.c
Warning:line 194, column 3
Value stored to 'sel' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pluma-taglist-plugin-panel.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/plugins/taglist -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I ../.. -I ../.. -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/gtksourceview-4 -I /usr/include/libpeas-1.0 -I /usr/include/gobject-introspection-1.0 -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/plugins/taglist -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-10-22-114445-13211-1 -x c pluma-taglist-plugin-panel.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * pluma-taglist-plugin-panel.c
3 * This file is part of pluma
4 *
5 * Copyright (C) 2005 - Paolo Maggi
6 * Copyright (C) 2012-2021 MATE Developers
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24/*
25 * Modified by the pluma Team, 2005. See the AUTHORS file for a
26 * list of people on the pluma Team.
27 * See the ChangeLog files for a list of changes.
28 *
29 * $Id$
30 */
31
32#ifdef HAVE_CONFIG_H1
33#include <config.h>
34#endif
35
36#include <string.h>
37
38#include "pluma-taglist-plugin-panel.h"
39#include "pluma-taglist-plugin-parser.h"
40
41#include <pluma/pluma-utils.h>
42#include <pluma/pluma-debug.h>
43
44#include <gtk/gtk.h>
45#include <gdk/gdkkeysyms.h>
46#include <glib/gi18n.h>
47
48enum
49{
50 COLUMN_TAG_NAME,
51 COLUMN_TAG_INDEX_IN_GROUP,
52 NUM_COLUMNS
53};
54
55struct _PlumaTaglistPluginPanelPrivate
56{
57 PlumaWindow *window;
58
59 GtkWidget *tag_groups_combo;
60 GtkWidget *tags_list;
61 GtkWidget *preview;
62
63 TagGroup *selected_tag_group;
64
65 gchar *data_dir;
66};
67
68G_DEFINE_DYNAMIC_TYPE_EXTENDED (PlumaTaglistPluginPanel,static void pluma_taglist_plugin_panel_init (PlumaTaglistPluginPanel
*self); static void pluma_taglist_plugin_panel_class_init (PlumaTaglistPluginPanelClass
*klass); static void pluma_taglist_plugin_panel_class_finalize
(PlumaTaglistPluginPanelClass *klass); static gpointer pluma_taglist_plugin_panel_parent_class
= ((void*)0); static GType pluma_taglist_plugin_panel_type_id
= 0; static gint PlumaTaglistPluginPanel_private_offset; static
void pluma_taglist_plugin_panel_class_intern_init (gpointer klass
) { pluma_taglist_plugin_panel_parent_class = g_type_class_peek_parent
(klass); if (PlumaTaglistPluginPanel_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaTaglistPluginPanel_private_offset); pluma_taglist_plugin_panel_class_init
((PlumaTaglistPluginPanelClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_taglist_plugin_panel_get_instance_private
(PlumaTaglistPluginPanel *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaTaglistPluginPanel_private_offset))
)); } GType pluma_taglist_plugin_panel_get_type (void) { return
pluma_taglist_plugin_panel_type_id; } static void pluma_taglist_plugin_panel_register_type
(GTypeModule *type_module) { GType g_define_type_id __attribute__
((__unused__)); const GTypeInfo g_define_type_info = { sizeof
(PlumaTaglistPluginPanelClass), (GBaseInitFunc) ((void*)0), (
GBaseFinalizeFunc) ((void*)0), (GClassInitFunc)(void (*)(void
)) pluma_taglist_plugin_panel_class_intern_init, (GClassFinalizeFunc
)(void (*)(void)) pluma_taglist_plugin_panel_class_finalize, (
(void*)0), sizeof (PlumaTaglistPluginPanel), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_taglist_plugin_panel_init, ((void*)0)
}; pluma_taglist_plugin_panel_type_id = g_type_module_register_type
(type_module, (gtk_box_get_type ()), "PlumaTaglistPluginPanel"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_taglist_plugin_panel_type_id; { { PlumaTaglistPluginPanel_private_offset
= sizeof (PlumaTaglistPluginPanelPrivate); } ; } }
69 pluma_taglist_plugin_panel,static void pluma_taglist_plugin_panel_init (PlumaTaglistPluginPanel
*self); static void pluma_taglist_plugin_panel_class_init (PlumaTaglistPluginPanelClass
*klass); static void pluma_taglist_plugin_panel_class_finalize
(PlumaTaglistPluginPanelClass *klass); static gpointer pluma_taglist_plugin_panel_parent_class
= ((void*)0); static GType pluma_taglist_plugin_panel_type_id
= 0; static gint PlumaTaglistPluginPanel_private_offset; static
void pluma_taglist_plugin_panel_class_intern_init (gpointer klass
) { pluma_taglist_plugin_panel_parent_class = g_type_class_peek_parent
(klass); if (PlumaTaglistPluginPanel_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaTaglistPluginPanel_private_offset); pluma_taglist_plugin_panel_class_init
((PlumaTaglistPluginPanelClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_taglist_plugin_panel_get_instance_private
(PlumaTaglistPluginPanel *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaTaglistPluginPanel_private_offset))
)); } GType pluma_taglist_plugin_panel_get_type (void) { return
pluma_taglist_plugin_panel_type_id; } static void pluma_taglist_plugin_panel_register_type
(GTypeModule *type_module) { GType g_define_type_id __attribute__
((__unused__)); const GTypeInfo g_define_type_info = { sizeof
(PlumaTaglistPluginPanelClass), (GBaseInitFunc) ((void*)0), (
GBaseFinalizeFunc) ((void*)0), (GClassInitFunc)(void (*)(void
)) pluma_taglist_plugin_panel_class_intern_init, (GClassFinalizeFunc
)(void (*)(void)) pluma_taglist_plugin_panel_class_finalize, (
(void*)0), sizeof (PlumaTaglistPluginPanel), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_taglist_plugin_panel_init, ((void*)0)
}; pluma_taglist_plugin_panel_type_id = g_type_module_register_type
(type_module, (gtk_box_get_type ()), "PlumaTaglistPluginPanel"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_taglist_plugin_panel_type_id; { { PlumaTaglistPluginPanel_private_offset
= sizeof (PlumaTaglistPluginPanelPrivate); } ; } }
70 GTK_TYPE_BOX,static void pluma_taglist_plugin_panel_init (PlumaTaglistPluginPanel
*self); static void pluma_taglist_plugin_panel_class_init (PlumaTaglistPluginPanelClass
*klass); static void pluma_taglist_plugin_panel_class_finalize
(PlumaTaglistPluginPanelClass *klass); static gpointer pluma_taglist_plugin_panel_parent_class
= ((void*)0); static GType pluma_taglist_plugin_panel_type_id
= 0; static gint PlumaTaglistPluginPanel_private_offset; static
void pluma_taglist_plugin_panel_class_intern_init (gpointer klass
) { pluma_taglist_plugin_panel_parent_class = g_type_class_peek_parent
(klass); if (PlumaTaglistPluginPanel_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaTaglistPluginPanel_private_offset); pluma_taglist_plugin_panel_class_init
((PlumaTaglistPluginPanelClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_taglist_plugin_panel_get_instance_private
(PlumaTaglistPluginPanel *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaTaglistPluginPanel_private_offset))
)); } GType pluma_taglist_plugin_panel_get_type (void) { return
pluma_taglist_plugin_panel_type_id; } static void pluma_taglist_plugin_panel_register_type
(GTypeModule *type_module) { GType g_define_type_id __attribute__
((__unused__)); const GTypeInfo g_define_type_info = { sizeof
(PlumaTaglistPluginPanelClass), (GBaseInitFunc) ((void*)0), (
GBaseFinalizeFunc) ((void*)0), (GClassInitFunc)(void (*)(void
)) pluma_taglist_plugin_panel_class_intern_init, (GClassFinalizeFunc
)(void (*)(void)) pluma_taglist_plugin_panel_class_finalize, (
(void*)0), sizeof (PlumaTaglistPluginPanel), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_taglist_plugin_panel_init, ((void*)0)
}; pluma_taglist_plugin_panel_type_id = g_type_module_register_type
(type_module, (gtk_box_get_type ()), "PlumaTaglistPluginPanel"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_taglist_plugin_panel_type_id; { { PlumaTaglistPluginPanel_private_offset
= sizeof (PlumaTaglistPluginPanelPrivate); } ; } }
71 0,static void pluma_taglist_plugin_panel_init (PlumaTaglistPluginPanel
*self); static void pluma_taglist_plugin_panel_class_init (PlumaTaglistPluginPanelClass
*klass); static void pluma_taglist_plugin_panel_class_finalize
(PlumaTaglistPluginPanelClass *klass); static gpointer pluma_taglist_plugin_panel_parent_class
= ((void*)0); static GType pluma_taglist_plugin_panel_type_id
= 0; static gint PlumaTaglistPluginPanel_private_offset; static
void pluma_taglist_plugin_panel_class_intern_init (gpointer klass
) { pluma_taglist_plugin_panel_parent_class = g_type_class_peek_parent
(klass); if (PlumaTaglistPluginPanel_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaTaglistPluginPanel_private_offset); pluma_taglist_plugin_panel_class_init
((PlumaTaglistPluginPanelClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_taglist_plugin_panel_get_instance_private
(PlumaTaglistPluginPanel *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaTaglistPluginPanel_private_offset))
)); } GType pluma_taglist_plugin_panel_get_type (void) { return
pluma_taglist_plugin_panel_type_id; } static void pluma_taglist_plugin_panel_register_type
(GTypeModule *type_module) { GType g_define_type_id __attribute__
((__unused__)); const GTypeInfo g_define_type_info = { sizeof
(PlumaTaglistPluginPanelClass), (GBaseInitFunc) ((void*)0), (
GBaseFinalizeFunc) ((void*)0), (GClassInitFunc)(void (*)(void
)) pluma_taglist_plugin_panel_class_intern_init, (GClassFinalizeFunc
)(void (*)(void)) pluma_taglist_plugin_panel_class_finalize, (
(void*)0), sizeof (PlumaTaglistPluginPanel), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_taglist_plugin_panel_init, ((void*)0)
}; pluma_taglist_plugin_panel_type_id = g_type_module_register_type
(type_module, (gtk_box_get_type ()), "PlumaTaglistPluginPanel"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_taglist_plugin_panel_type_id; { { PlumaTaglistPluginPanel_private_offset
= sizeof (PlumaTaglistPluginPanelPrivate); } ; } }
72 G_ADD_PRIVATE_DYNAMIC(PlumaTaglistPluginPanel))static void pluma_taglist_plugin_panel_init (PlumaTaglistPluginPanel
*self); static void pluma_taglist_plugin_panel_class_init (PlumaTaglistPluginPanelClass
*klass); static void pluma_taglist_plugin_panel_class_finalize
(PlumaTaglistPluginPanelClass *klass); static gpointer pluma_taglist_plugin_panel_parent_class
= ((void*)0); static GType pluma_taglist_plugin_panel_type_id
= 0; static gint PlumaTaglistPluginPanel_private_offset; static
void pluma_taglist_plugin_panel_class_intern_init (gpointer klass
) { pluma_taglist_plugin_panel_parent_class = g_type_class_peek_parent
(klass); if (PlumaTaglistPluginPanel_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaTaglistPluginPanel_private_offset); pluma_taglist_plugin_panel_class_init
((PlumaTaglistPluginPanelClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_taglist_plugin_panel_get_instance_private
(PlumaTaglistPluginPanel *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaTaglistPluginPanel_private_offset))
)); } GType pluma_taglist_plugin_panel_get_type (void) { return
pluma_taglist_plugin_panel_type_id; } static void pluma_taglist_plugin_panel_register_type
(GTypeModule *type_module) { GType g_define_type_id __attribute__
((__unused__)); const GTypeInfo g_define_type_info = { sizeof
(PlumaTaglistPluginPanelClass), (GBaseInitFunc) ((void*)0), (
GBaseFinalizeFunc) ((void*)0), (GClassInitFunc)(void (*)(void
)) pluma_taglist_plugin_panel_class_intern_init, (GClassFinalizeFunc
)(void (*)(void)) pluma_taglist_plugin_panel_class_finalize, (
(void*)0), sizeof (PlumaTaglistPluginPanel), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_taglist_plugin_panel_init, ((void*)0)
}; pluma_taglist_plugin_panel_type_id = g_type_module_register_type
(type_module, (gtk_box_get_type ()), "PlumaTaglistPluginPanel"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_taglist_plugin_panel_type_id; { { PlumaTaglistPluginPanel_private_offset
= sizeof (PlumaTaglistPluginPanelPrivate); } ; } }
73
74enum
75{
76 PROP_0,
77 PROP_WINDOW,
78};
79
80static void
81set_window (PlumaTaglistPluginPanel *panel,
82 PlumaWindow *window)
83{
84 g_return_if_fail (panel->priv->window == NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_21
; if (panel->priv->window == ((void*)0)) _g_boolean_var_21
= 1; else _g_boolean_var_21 = 0; _g_boolean_var_21; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "panel->priv->window == NULL"); return;
} } while (0)
;
85 g_return_if_fail (PLUMA_IS_WINDOW (window))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_22
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_22
= 1; else _g_boolean_var_22 = 0; _g_boolean_var_22; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "PLUMA_IS_WINDOW (window)"); return; } } while
(0)
;
86
87 panel->priv->window = window;
88
89 /* TODO */
90}
91
92static void
93pluma_taglist_plugin_panel_set_property (GObject *object,
94 guint prop_id,
95 const GValue *value,
96 GParamSpec *pspec)
97{
98 PlumaTaglistPluginPanel *panel = PLUMA_TAGLIST_PLUGIN_PANEL (object)((((PlumaTaglistPluginPanel*) (void *) ((object)))));
99
100 switch (prop_id)
101 {
102 case PROP_WINDOW:
103 set_window (panel, g_value_get_object (value));
104 break;
105
106 default:
107 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "pluma-taglist-plugin-panel.c", 107, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
108 break;
109 }
110}
111
112static void
113pluma_taglist_plugin_panel_get_property (GObject *object,
114 guint prop_id,
115 GValue *value,
116 GParamSpec *pspec)
117{
118 PlumaTaglistPluginPanel *panel = PLUMA_TAGLIST_PLUGIN_PANEL (object)((((PlumaTaglistPluginPanel*) (void *) ((object)))));
119
120 switch (prop_id)
121 {
122 case PROP_WINDOW:
123 panel->priv = pluma_taglist_plugin_panel_get_instance_private (panel);
124 g_value_set_object (value, panel->priv->window);
125 break;
126 default:
127 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "pluma-taglist-plugin-panel.c", 127, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
128 break;
129 }
130}
131
132static void
133pluma_taglist_plugin_panel_finalize (GObject *object)
134{
135 PlumaTaglistPluginPanel *panel = PLUMA_TAGLIST_PLUGIN_PANEL (object)((((PlumaTaglistPluginPanel*) (void *) ((object)))));
136
137 g_free (panel->priv->data_dir);
138
139 G_OBJECT_CLASS (pluma_taglist_plugin_panel_parent_class)((((GObjectClass*) (void *) ((pluma_taglist_plugin_panel_parent_class
)))))
->finalize (object);
140}
141
142static void
143pluma_taglist_plugin_panel_class_init (PlumaTaglistPluginPanelClass *klass)
144{
145 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) ((klass)))));
146
147 object_class->finalize = pluma_taglist_plugin_panel_finalize;
148 object_class->get_property = pluma_taglist_plugin_panel_get_property;
149 object_class->set_property = pluma_taglist_plugin_panel_set_property;
150
151 g_object_class_install_property (object_class,
152 PROP_WINDOW,
153 g_param_spec_object ("window",
154 "Window",
155 "The PlumaWindow this PlumaTaglistPluginPanel is associated with",
156 PLUMA_TYPE_WINDOW(pluma_window_get_type()),
157 G_PARAM_READWRITE |
158 G_PARAM_CONSTRUCT_ONLY));
159}
160
161static void
162pluma_taglist_plugin_panel_class_finalize (PlumaTaglistPluginPanelClass *klass)
163{
164 /* dummy function - used by G_DEFINE_DYNAMIC_TYPE_EXTENDED */
165}
166
167static void
168insert_tag (PlumaTaglistPluginPanel *panel,
169 Tag *tag,
170 gboolean grab_focus)
171{
172 PlumaView *view;
173 GtkTextBuffer *buffer;
174 GtkTextIter start, end;
175 GtkTextIter cursor;
176 gboolean sel = FALSE(0);
177
178 pluma_debug (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-taglist-plugin-panel.c", 178, ((const
char*) (__func__))
);
179
180 view = pluma_window_get_active_view (panel->priv->window);
181 g_return_if_fail (view != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_23
; if (view != ((void*)0)) _g_boolean_var_23 = 1; else _g_boolean_var_23
= 0; _g_boolean_var_23; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "view != NULL"); return
; } } while (0)
;
182
183 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)((((GtkTextView*) (void *) ((view))))));
184
185 gtk_text_buffer_begin_user_action (buffer);
186
187 /* always insert the begin tag at the beginning of the selection
188 * and the end tag at the end, if there is no selection they will
189 * be automatically inserted at the cursor position.
190 */
191
192 if (tag->begin != NULL((void*)0))
193 {
194 sel = gtk_text_buffer_get_selection_bounds (buffer,
Value stored to 'sel' is never read
195 &start,
196 &end);
197
198 gtk_text_buffer_insert (buffer,
199 &start,
200 (gchar *)tag->begin,
201 -1);
202
203 /* get iterators again since they have been invalidated and move
204 * the cursor after the selection */
205 gtk_text_buffer_get_selection_bounds (buffer,
206 &start,
207 &cursor);
208 }
209
210 if (tag->end != NULL((void*)0))
211 {
212 sel = gtk_text_buffer_get_selection_bounds (buffer,
213 &start,
214 &end);
215
216 gtk_text_buffer_insert (buffer,
217 &end,
218 (gchar *)tag->end,
219 -1);
220
221 /* if there is no selection and we have a paired tag, move the
222 * cursor between the pair, otherwise move it at the end */
223 if (!sel)
224 {
225 gint offset;
226
227 offset = gtk_text_iter_get_offset (&end) -
228 g_utf8_strlen ((gchar *)tag->end, -1);
229
230 gtk_text_buffer_get_iter_at_offset (buffer,
231 &end,
232 offset);
233 }
234
235 cursor = end;
236 }
237
238 gtk_text_buffer_place_cursor (buffer, &cursor);
239
240 gtk_text_buffer_end_user_action (buffer);
241
242 if (grab_focus)
243 gtk_widget_grab_focus (GTK_WIDGET (view)((((GtkWidget*) (void *) ((view))))));
244}
245
246static void
247tag_list_row_activated_cb (GtkTreeView *tag_list,
248 GtkTreePath *path,
249 GtkTreeViewColumn *column,
250 PlumaTaglistPluginPanel *panel)
251{
252 GtkTreeIter iter;
253 GtkTreeModel *model;
254 gint index;
255
256 pluma_debug (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-taglist-plugin-panel.c", 256, ((const
char*) (__func__))
);
257
258 model = gtk_tree_view_get_model (tag_list);
259
260 gtk_tree_model_get_iter (model, &iter, path);
261 g_return_if_fail (&iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_24
; if (&iter != ((void*)0)) _g_boolean_var_24 = 1; else _g_boolean_var_24
= 0; _g_boolean_var_24; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "&iter != NULL"
); return; } } while (0)
;
262
263 gtk_tree_model_get (model, &iter, COLUMN_TAG_INDEX_IN_GROUP, &index, -1);
264
265 pluma_debug_message (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-taglist-plugin-panel.c", 265, ((const
char*) (__func__))
, "Index: %d", index);
266
267 insert_tag (panel,
268 (Tag*)g_list_nth_data (panel->priv->selected_tag_group->tags, index),
269 TRUE(!(0)));
270}
271
272static gboolean
273tag_list_key_press_event_cb (GtkTreeView *tag_list,
274 GdkEventKey *event,
275 PlumaTaglistPluginPanel *panel)
276{
277 gboolean grab_focus;
278
279 grab_focus = (event->state & GDK_CONTROL_MASK) != 0;
280
281 if (event->keyval == GDK_KEY_Return0xff0d)
282 {
283 GtkTreeModel *model;
284 GtkTreeSelection *selection;
285 GtkTreeIter iter;
286 gint index;
287
288 pluma_debug_message (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-taglist-plugin-panel.c", 288, ((const
char*) (__func__))
, "RETURN Pressed");
289
290 model = gtk_tree_view_get_model (tag_list);
291
292 selection = gtk_tree_view_get_selection (tag_list);
293
294 if (gtk_tree_selection_get_selected (selection, NULL((void*)0), &iter))
295 {
296 gtk_tree_model_get (model, &iter, COLUMN_TAG_INDEX_IN_GROUP, &index, -1);
297
298 pluma_debug_message (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-taglist-plugin-panel.c", 298, ((const
char*) (__func__))
, "Index: %d", index);
299
300 insert_tag (panel,
301 (Tag*)g_list_nth_data (panel->priv->selected_tag_group->tags, index),
302 grab_focus);
303 }
304
305 return TRUE(!(0));
306 }
307
308 return FALSE(0);
309}
310
311static GtkTreeModel*
312create_model (PlumaTaglistPluginPanel *panel)
313{
314 gint i = 0;
315 GtkListStore *store;
316 GtkTreeIter iter;
317 GList *list;
318
319 pluma_debug (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-taglist-plugin-panel.c", 319, ((const
char*) (__func__))
);
320
321 /* create list store */
322 store = gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING((GType) ((16) << (2))), G_TYPE_INT((GType) ((6) << (2))));
323
324 /* add data to the list store */
325 list = panel->priv->selected_tag_group->tags;
326
327 while (list != NULL((void*)0))
328 {
329 const gchar* tag_name;
330
331 tag_name = (gchar *)((Tag*)list->data)->name;
332
333 pluma_debug_message (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-taglist-plugin-panel.c", 333, ((const
char*) (__func__))
, "%d : %s", i, tag_name);
334
335 gtk_list_store_append (store, &iter);
336 gtk_list_store_set (store, &iter,
337 COLUMN_TAG_NAME, tag_name,
338 COLUMN_TAG_INDEX_IN_GROUP, i,
339 -1);
340 ++i;
341
342 list = g_list_next (list)((list) ? (((GList *)(list))->next) : ((void*)0));
343 }
344
345 pluma_debug_message (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-taglist-plugin-panel.c", 345, ((const
char*) (__func__))
, "Rows: %d ",
346 gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store)((((GtkTreeModel*) (void *) ((store))))), NULL((void*)0)));
347
348 return GTK_TREE_MODEL (store)((((GtkTreeModel*) (void *) ((store)))));
349}
350
351static void
352populate_tags_list (PlumaTaglistPluginPanel *panel)
353{
354 GtkTreeModel* model;
355
356 pluma_debug (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-taglist-plugin-panel.c", 356, ((const
char*) (__func__))
);
357
358 g_return_if_fail (taglist != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_25
; if (taglist != ((void*)0)) _g_boolean_var_25 = 1; else _g_boolean_var_25
= 0; _g_boolean_var_25; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "taglist != NULL"
); return; } } while (0)
;
359
360 model = create_model (panel);
361 gtk_tree_view_set_model (GTK_TREE_VIEW (panel->priv->tags_list)((((GtkTreeView*) (void *) ((panel->priv->tags_list))))
)
,
362 model);
363 g_object_unref (model);
364}
365
366static TagGroup *
367find_tag_group (const gchar *name)
368{
369 GList *l;
370
371 pluma_debug (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-taglist-plugin-panel.c", 371, ((const
char*) (__func__))
);
372
373 g_return_val_if_fail (taglist != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_26
; if (taglist != ((void*)0)) _g_boolean_var_26 = 1; else _g_boolean_var_26
= 0; _g_boolean_var_26; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "taglist != NULL"
); return (((void*)0)); } } while (0)
;
374
375 for (l = taglist->tag_groups; l != NULL((void*)0); l = g_list_next (l)((l) ? (((GList *)(l))->next) : ((void*)0)))
376 {
377 if (strcmp (name, (gchar *)((TagGroup*)l->data)->name) == 0)
378 return (TagGroup*)l->data;
379 }
380
381 return NULL((void*)0);
382}
383
384static void
385populate_tag_groups_combo (PlumaTaglistPluginPanel *panel)
386{
387 GList *l;
388 GtkComboBox *combo;
389 GtkComboBoxText *combotext;
390
391 pluma_debug (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-taglist-plugin-panel.c", 391, ((const
char*) (__func__))
);
392
393 combo = GTK_COMBO_BOX (panel->priv->tag_groups_combo)((((GtkComboBox*) (void *) ((panel->priv->tag_groups_combo
)))))
;
394 combotext = GTK_COMBO_BOX_TEXT (panel->priv->tag_groups_combo)((((GtkComboBoxText*) (void *) ((panel->priv->tag_groups_combo
)))))
;
395
396 if (taglist == NULL((void*)0))
397 return;
398
399 for (l = taglist->tag_groups; l != NULL((void*)0); l = g_list_next (l)((l) ? (((GList *)(l))->next) : ((void*)0)))
400 {
401 gtk_combo_box_text_append_text (combotext,
402 (gchar *)((TagGroup*)l->data)->name);
403 }
404
405 gtk_combo_box_set_active (combo, 0);
406
407 return;
408}
409
410static void
411selected_group_changed (GtkComboBox *combo,
412 PlumaTaglistPluginPanel *panel)
413{
414 gchar* group_name;
415
416 pluma_debug (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-taglist-plugin-panel.c", 416, ((const
char*) (__func__))
);
417
418 group_name = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (combo)((((GtkComboBoxText*) (void *) ((combo))))));
419
420 if ((group_name == NULL((void*)0)) || (*group_name == '\0'))
421 {
422 g_free (group_name);
423 return;
424 }
425
426 if ((panel->priv->selected_tag_group == NULL((void*)0)) ||
427 (strcmp (group_name, (gchar *)panel->priv->selected_tag_group->name) != 0))
428 {
429 panel->priv->selected_tag_group = find_tag_group (group_name);
430 g_return_if_fail (panel->priv->selected_tag_group != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_27
; if (panel->priv->selected_tag_group != ((void*)0)) _g_boolean_var_27
= 1; else _g_boolean_var_27 = 0; _g_boolean_var_27; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "panel->priv->selected_tag_group != NULL"
); return; } } while (0)
;
431
432 pluma_debug_message (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-taglist-plugin-panel.c", 432, ((const
char*) (__func__))
,
433 "New selected group: %s",
434 panel->priv->selected_tag_group->name);
435
436 populate_tags_list (panel);
437 }
438
439 /* Clean up preview */
440 gtk_label_set_text (GTK_LABEL (panel->priv->preview)((((GtkLabel*) (void *) ((panel->priv->preview))))),
441 "");
442
443 g_free (group_name);
444}
445
446static gchar *
447create_preview_string (Tag *tag)
448{
449 GString *str;
450
451 str = g_string_new ("<tt><small>");
452
453 if (tag->begin != NULL((void*)0))
454 {
455 gchar *markup;
456
457 markup = g_markup_escape_text ((gchar *)tag->begin, -1);
458 g_string_append (str, markup)(__builtin_constant_p (markup) ? __extension__ ({ const char *
const __val = (markup); g_string_append_len_inline (str, __val
, (__builtin_expect (__extension__ ({ int _g_boolean_var_28; if
(__val != ((void*)0)) _g_boolean_var_28 = 1; else _g_boolean_var_28
= 0; _g_boolean_var_28; }), 1)) ? (gssize) strlen (((__val) +
!(__val))) : (gssize) -1); }) : g_string_append_len_inline (
str, markup, (gssize) -1))
;
459 g_free (markup);
460 }
461
462 if (tag->end != NULL((void*)0))
463 {
464 gchar *markup;
465
466 markup = g_markup_escape_text ((gchar *)tag->end, -1);
467 g_string_append (str, markup)(__builtin_constant_p (markup) ? __extension__ ({ const char *
const __val = (markup); g_string_append_len_inline (str, __val
, (__builtin_expect (__extension__ ({ int _g_boolean_var_29; if
(__val != ((void*)0)) _g_boolean_var_29 = 1; else _g_boolean_var_29
= 0; _g_boolean_var_29; }), 1)) ? (gssize) strlen (((__val) +
!(__val))) : (gssize) -1); }) : g_string_append_len_inline (
str, markup, (gssize) -1))
;
468 g_free (markup);
469 }
470
471 g_string_append (str, "</small></tt>")(__builtin_constant_p ("</small></tt>") ? __extension__
({ const char * const __val = ("</small></tt>");
g_string_append_len_inline (str, __val, (__builtin_expect (__extension__
({ int _g_boolean_var_30; if (__val != ((void*)0)) _g_boolean_var_30
= 1; else _g_boolean_var_30 = 0; _g_boolean_var_30; }), 1)) ?
(gssize) strlen (((__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(str, "</small></tt>", (gssize) -1))
;
472
473 return g_string_free (str, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((str)
, ((0))) : g_string_free_and_steal (str)) : (g_string_free) (
(str), ((0))))
;
474}
475
476static void
477update_preview (PlumaTaglistPluginPanel *panel,
478 Tag *tag)
479{
480 gchar *str;
481
482 str = create_preview_string (tag);
483
484 gtk_label_set_markup (GTK_LABEL (panel->priv->preview)((((GtkLabel*) (void *) ((panel->priv->preview))))),
485 str);
486
487 g_free (str);
488}
489
490static void
491tag_list_cursor_changed_cb (GtkTreeView *tag_list,
492 gpointer data)
493{
494 GtkTreeModel *model;
495 GtkTreeSelection *selection;
496 GtkTreeIter iter;
497 gint index;
498
499 PlumaTaglistPluginPanel *panel = (PlumaTaglistPluginPanel *)data;
500
501 model = gtk_tree_view_get_model (tag_list);
502
503 selection = gtk_tree_view_get_selection (tag_list);
504
505 if (gtk_tree_selection_get_selected (selection, NULL((void*)0), &iter))
506 {
507 gtk_tree_model_get (model, &iter, COLUMN_TAG_INDEX_IN_GROUP, &index, -1);
508
509 pluma_debug_message (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-taglist-plugin-panel.c", 509, ((const
char*) (__func__))
, "Index: %d", index);
510
511 update_preview (panel,
512 (Tag*)g_list_nth_data (panel->priv->selected_tag_group->tags, index));
513 }
514}
515
516static gboolean
517tags_list_query_tooltip_cb (GtkWidget *widget,
518 gint x,
519 gint y,
520 gboolean keyboard_tip,
521 GtkTooltip *tooltip,
522 PlumaTaglistPluginPanel *panel)
523{
524 GtkTreeIter iter;
525 GtkTreeModel *model;
526 GtkTreePath *path = NULL((void*)0);
527 gint index;
528 Tag *tag;
529
530 model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)((((GtkTreeView*) (void *) ((widget))))));
531
532 if (keyboard_tip)
533 {
534 gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget)((((GtkTreeView*) (void *) ((widget))))),
535 &path,
536 NULL((void*)0));
537
538 if (path == NULL((void*)0))
539 {
540 return FALSE(0);
541 }
542 }
543 else
544 {
545 gint bin_x, bin_y;
546
547 gtk_tree_view_convert_widget_to_bin_window_coords (GTK_TREE_VIEW (widget)((((GtkTreeView*) (void *) ((widget))))),
548 x, y,
549 &bin_x, &bin_y);
550
551 if (!gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget)((((GtkTreeView*) (void *) ((widget))))),
552 bin_x, bin_y,
553 &path,
554 NULL((void*)0), NULL((void*)0), NULL((void*)0)))
555 {
556 return FALSE(0);
557 }
558 }
559
560 gtk_tree_model_get_iter (model, &iter, path);
561 gtk_tree_model_get (model, &iter,
562 COLUMN_TAG_INDEX_IN_GROUP, &index,
563 -1);
564
565 tag = g_list_nth_data (panel->priv->selected_tag_group->tags, index);
566 if (tag != NULL((void*)0))
567 {
568 gchar *tip;
569
570 tip = create_preview_string (tag);
571 gtk_tooltip_set_markup (tooltip, tip);
572 g_free (tip);
573 gtk_tree_path_free (path);
574
575 return TRUE(!(0));
576 }
577
578 gtk_tree_path_free (path);
579
580 return FALSE(0);
581}
582
583static gboolean
584draw_event_cb (GtkWidget *panel,
585 cairo_t *cr,
586 gpointer user_data)
587{
588 PlumaTaglistPluginPanel *ppanel = PLUMA_TAGLIST_PLUGIN_PANEL (panel)((((PlumaTaglistPluginPanel*) (void *) ((panel)))));
589
590 pluma_debug (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-taglist-plugin-panel.c", 590, ((const
char*) (__func__))
);
591
592 /* If needed load taglists from files at the first expose */
593 if (taglist == NULL((void*)0))
594 create_taglist (ppanel->priv->data_dir);
595
596 /* And populate combo box */
597 populate_tag_groups_combo (PLUMA_TAGLIST_PLUGIN_PANEL (panel)((((PlumaTaglistPluginPanel*) (void *) ((panel))))));
598
599 /* We need to manage only the first draw -> disconnect */
600 g_signal_handlers_disconnect_by_func (panel, draw_event_cb, NULL)g_signal_handlers_disconnect_matched ((panel), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (draw_event_cb), (((void*)0)))
;
601
602 return FALSE(0);
603}
604
605static void
606set_combo_tooltip (GtkWidget *widget,
607 gpointer data)
608{
609 if (GTK_IS_BUTTON (widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(widget)); GType __t = ((gtk_button_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
610 {
611 gtk_widget_set_tooltip_text (widget,
612 _("Select the group of tags you want to use")dcgettext (((void*)0), "Select the group of tags you want to use"
, 5)
);
613 }
614}
615
616static void
617realize_tag_groups_combo (GtkWidget *combo,
618 gpointer data)
619{
620 gtk_container_forall (GTK_CONTAINER (combo)((((GtkContainer*) (void *) ((combo))))),
621 set_combo_tooltip,
622 NULL((void*)0));
623}
624
625static void
626add_preview_widget (PlumaTaglistPluginPanel *panel)
627{
628 GtkWidget *expander;
629 GtkWidget *frame;
630
631 expander = gtk_expander_new_with_mnemonic (_("_Preview")dcgettext (((void*)0), "_Preview", 5));
632
633 panel->priv->preview = gtk_label_new (NULL((void*)0));
634 gtk_widget_set_size_request (panel->priv->preview, -1, 80);
635
636 gtk_label_set_line_wrap (GTK_LABEL (panel->priv->preview)((((GtkLabel*) (void *) ((panel->priv->preview))))), TRUE(!(0)));
637 gtk_label_set_use_markup (GTK_LABEL (panel->priv->preview)((((GtkLabel*) (void *) ((panel->priv->preview))))), TRUE(!(0)));
638 gtk_widget_set_halign (panel->priv->preview, GTK_ALIGN_START);
639 gtk_widget_set_valign (panel->priv->preview, GTK_ALIGN_START);
640 gtk_widget_set_margin_start (panel->priv->preview, 6);
641 gtk_widget_set_margin_end (panel->priv->preview, 6);
642 gtk_widget_set_margin_top (panel->priv->preview, 6);
643 gtk_widget_set_margin_bottom (panel->priv->preview, 6);
644 gtk_label_set_selectable (GTK_LABEL (panel->priv->preview)((((GtkLabel*) (void *) ((panel->priv->preview))))), TRUE(!(0)));
645 gtk_label_set_selectable (GTK_LABEL (panel->priv->preview)((((GtkLabel*) (void *) ((panel->priv->preview))))), TRUE(!(0)));
646 gtk_label_set_ellipsize (GTK_LABEL (panel->priv->preview)((((GtkLabel*) (void *) ((panel->priv->preview))))),
647 PANGO_ELLIPSIZE_END);
648
649 frame = gtk_frame_new (0);
650 gtk_frame_set_shadow_type (GTK_FRAME (frame)((((GtkFrame*) (void *) ((frame))))), GTK_SHADOW_IN);
651
652 gtk_container_add (GTK_CONTAINER (frame)((((GtkContainer*) (void *) ((frame))))),
653 panel->priv->preview);
654
655 gtk_container_add (GTK_CONTAINER (expander)((((GtkContainer*) (void *) ((expander))))),
656 frame);
657
658 gtk_box_pack_start (GTK_BOX (panel)((((GtkBox*) (void *) ((panel))))), expander, FALSE(0), FALSE(0), 0);
659
660 gtk_widget_show_all (expander);
661}
662
663static void
664pluma_taglist_plugin_panel_init (PlumaTaglistPluginPanel *panel)
665{
666 GtkWidget *sw;
667 GtkTreeViewColumn *column;
668 GtkCellRenderer *cell;
669 GList *focus_chain = NULL((void*)0);
670
671 pluma_debug (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-taglist-plugin-panel.c", 671, ((const
char*) (__func__))
);
672
673 panel->priv = pluma_taglist_plugin_panel_get_instance_private (panel);
674 panel->priv->data_dir = NULL((void*)0);
675
676 gtk_orientable_set_orientation (GTK_ORIENTABLE (panel)((((GtkOrientable*) (void *) ((panel))))),
677 GTK_ORIENTATION_VERTICAL);
678
679 /* Build the window content */
680 panel->priv->tag_groups_combo = gtk_combo_box_text_new ();
681 gtk_box_pack_start (GTK_BOX (panel)((((GtkBox*) (void *) ((panel))))),
682 panel->priv->tag_groups_combo,
683 FALSE(0),
684 TRUE(!(0)),
685 0);
686
687 g_signal_connect (panel->priv->tag_groups_combo,g_signal_connect_data ((panel->priv->tag_groups_combo),
("realize"), (((GCallback) (realize_tag_groups_combo))), (panel
), ((void*)0), (GConnectFlags) 0)
688 "realize",g_signal_connect_data ((panel->priv->tag_groups_combo),
("realize"), (((GCallback) (realize_tag_groups_combo))), (panel
), ((void*)0), (GConnectFlags) 0)
689 G_CALLBACK (realize_tag_groups_combo),g_signal_connect_data ((panel->priv->tag_groups_combo),
("realize"), (((GCallback) (realize_tag_groups_combo))), (panel
), ((void*)0), (GConnectFlags) 0)
690 panel)g_signal_connect_data ((panel->priv->tag_groups_combo),
("realize"), (((GCallback) (realize_tag_groups_combo))), (panel
), ((void*)0), (GConnectFlags) 0)
;
691
692 sw = gtk_scrolled_window_new (NULL((void*)0), NULL((void*)0));
693
694 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw)((((GtkScrolledWindow*) (void *) ((sw))))),
695 GTK_POLICY_AUTOMATIC,
696 GTK_POLICY_AUTOMATIC);
697 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw)((((GtkScrolledWindow*) (void *) ((sw))))),
698 GTK_SHADOW_IN);
699 gtk_box_pack_start (GTK_BOX (panel)((((GtkBox*) (void *) ((panel))))), sw, TRUE(!(0)), TRUE(!(0)), 0);
700
701 /* Create tree view */
702 panel->priv->tags_list = gtk_tree_view_new ();
703
704 pluma_utils_set_atk_name_description (panel->priv->tag_groups_combo,
705 _("Available Tag Lists")dcgettext (((void*)0), "Available Tag Lists", 5),
706 NULL((void*)0));
707 pluma_utils_set_atk_name_description (panel->priv->tags_list,
708 _("Tags")dcgettext (((void*)0), "Tags", 5),
709 NULL((void*)0));
710 pluma_utils_set_atk_relation (panel->priv->tag_groups_combo,
711 panel->priv->tags_list,
712 ATK_RELATION_CONTROLLER_FOR);
713 pluma_utils_set_atk_relation (panel->priv->tags_list,
714 panel->priv->tag_groups_combo,
715 ATK_RELATION_CONTROLLED_BY);
716
717 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (panel->priv->tags_list)((((GtkTreeView*) (void *) ((panel->priv->tags_list))))
)
, FALSE(0));
718
719 g_object_set (panel->priv->tags_list, "has-tooltip", TRUE(!(0)), NULL((void*)0));
720
721 /* Add the tags column */
722 cell = gtk_cell_renderer_text_new ();
723 column = gtk_tree_view_column_new_with_attributes (_("Tags")dcgettext (((void*)0), "Tags", 5),
724 cell,
725 "text",
726 COLUMN_TAG_NAME,
727 NULL((void*)0));
728 gtk_tree_view_append_column (GTK_TREE_VIEW (panel->priv->tags_list)((((GtkTreeView*) (void *) ((panel->priv->tags_list))))
)
,
729 column);
730
731 gtk_tree_view_set_search_column (GTK_TREE_VIEW (panel->priv->tags_list)((((GtkTreeView*) (void *) ((panel->priv->tags_list))))
)
,
732 COLUMN_TAG_NAME);
733
734 gtk_container_add (GTK_CONTAINER (sw)((((GtkContainer*) (void *) ((sw))))), panel->priv->tags_list);
735
736 focus_chain = g_list_prepend (focus_chain, panel->priv->tags_list);
737 focus_chain = g_list_prepend (focus_chain, panel->priv->tag_groups_combo);
738
739 gtk_container_set_focus_chain (GTK_CONTAINER (panel)((((GtkContainer*) (void *) ((panel))))),
740 focus_chain);
741 g_list_free (focus_chain);
742
743 add_preview_widget (panel);
744
745 gtk_widget_show_all (GTK_WIDGET (sw)((((GtkWidget*) (void *) ((sw))))));
746 gtk_widget_show (GTK_WIDGET (panel->priv->tag_groups_combo)((((GtkWidget*) (void *) ((panel->priv->tag_groups_combo
)))))
);
747
748 g_signal_connect_after (panel->priv->tags_list,g_signal_connect_data ((panel->priv->tags_list), ("row_activated"
), (((GCallback) (tag_list_row_activated_cb))), (panel), ((void
*)0), G_CONNECT_AFTER)
749 "row_activated",g_signal_connect_data ((panel->priv->tags_list), ("row_activated"
), (((GCallback) (tag_list_row_activated_cb))), (panel), ((void
*)0), G_CONNECT_AFTER)
750 G_CALLBACK (tag_list_row_activated_cb),g_signal_connect_data ((panel->priv->tags_list), ("row_activated"
), (((GCallback) (tag_list_row_activated_cb))), (panel), ((void
*)0), G_CONNECT_AFTER)
751 panel)g_signal_connect_data ((panel->priv->tags_list), ("row_activated"
), (((GCallback) (tag_list_row_activated_cb))), (panel), ((void
*)0), G_CONNECT_AFTER)
;
752 g_signal_connect (panel->priv->tags_list,g_signal_connect_data ((panel->priv->tags_list), ("key_press_event"
), (((GCallback) (tag_list_key_press_event_cb))), (panel), ((
void*)0), (GConnectFlags) 0)
753 "key_press_event",g_signal_connect_data ((panel->priv->tags_list), ("key_press_event"
), (((GCallback) (tag_list_key_press_event_cb))), (panel), ((
void*)0), (GConnectFlags) 0)
754 G_CALLBACK (tag_list_key_press_event_cb),g_signal_connect_data ((panel->priv->tags_list), ("key_press_event"
), (((GCallback) (tag_list_key_press_event_cb))), (panel), ((
void*)0), (GConnectFlags) 0)
755 panel)g_signal_connect_data ((panel->priv->tags_list), ("key_press_event"
), (((GCallback) (tag_list_key_press_event_cb))), (panel), ((
void*)0), (GConnectFlags) 0)
;
756 g_signal_connect (panel->priv->tags_list,g_signal_connect_data ((panel->priv->tags_list), ("query-tooltip"
), (((GCallback) (tags_list_query_tooltip_cb))), (panel), ((void
*)0), (GConnectFlags) 0)
757 "query-tooltip",g_signal_connect_data ((panel->priv->tags_list), ("query-tooltip"
), (((GCallback) (tags_list_query_tooltip_cb))), (panel), ((void
*)0), (GConnectFlags) 0)
758 G_CALLBACK (tags_list_query_tooltip_cb),g_signal_connect_data ((panel->priv->tags_list), ("query-tooltip"
), (((GCallback) (tags_list_query_tooltip_cb))), (panel), ((void
*)0), (GConnectFlags) 0)
759 panel)g_signal_connect_data ((panel->priv->tags_list), ("query-tooltip"
), (((GCallback) (tags_list_query_tooltip_cb))), (panel), ((void
*)0), (GConnectFlags) 0)
;
760 g_signal_connect (panel->priv->tags_list,g_signal_connect_data ((panel->priv->tags_list), ("cursor_changed"
), (((GCallback) (tag_list_cursor_changed_cb))), (panel), ((void
*)0), (GConnectFlags) 0)
761 "cursor_changed",g_signal_connect_data ((panel->priv->tags_list), ("cursor_changed"
), (((GCallback) (tag_list_cursor_changed_cb))), (panel), ((void
*)0), (GConnectFlags) 0)
762 G_CALLBACK (tag_list_cursor_changed_cb),g_signal_connect_data ((panel->priv->tags_list), ("cursor_changed"
), (((GCallback) (tag_list_cursor_changed_cb))), (panel), ((void
*)0), (GConnectFlags) 0)
763 panel)g_signal_connect_data ((panel->priv->tags_list), ("cursor_changed"
), (((GCallback) (tag_list_cursor_changed_cb))), (panel), ((void
*)0), (GConnectFlags) 0)
;
764 g_signal_connect (panel->priv->tag_groups_combo,g_signal_connect_data ((panel->priv->tag_groups_combo),
("changed"), (((GCallback) (selected_group_changed))), (panel
), ((void*)0), (GConnectFlags) 0)
765 "changed",g_signal_connect_data ((panel->priv->tag_groups_combo),
("changed"), (((GCallback) (selected_group_changed))), (panel
), ((void*)0), (GConnectFlags) 0)
766 G_CALLBACK (selected_group_changed),g_signal_connect_data ((panel->priv->tag_groups_combo),
("changed"), (((GCallback) (selected_group_changed))), (panel
), ((void*)0), (GConnectFlags) 0)
767 panel)g_signal_connect_data ((panel->priv->tag_groups_combo),
("changed"), (((GCallback) (selected_group_changed))), (panel
), ((void*)0), (GConnectFlags) 0)
;
768 g_signal_connect (panel,g_signal_connect_data ((panel), ("draw"), (((GCallback) (draw_event_cb
))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
769 "draw",g_signal_connect_data ((panel), ("draw"), (((GCallback) (draw_event_cb
))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
770 G_CALLBACK (draw_event_cb),g_signal_connect_data ((panel), ("draw"), (((GCallback) (draw_event_cb
))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
771 NULL)g_signal_connect_data ((panel), ("draw"), (((GCallback) (draw_event_cb
))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
;
772}
773
774GtkWidget *
775pluma_taglist_plugin_panel_new (PlumaWindow *window,
776 const gchar *data_dir)
777{
778 PlumaTaglistPluginPanel *panel;
779
780 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_31
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_31
= 1; else _g_boolean_var_31 = 0; _g_boolean_var_31; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void*)
0)); } } while (0)
;
781
782 panel = g_object_new (PLUMA_TYPE_TAGLIST_PLUGIN_PANEL(pluma_taglist_plugin_panel_get_type()),
783 "window", window,
784 NULL((void*)0));
785
786 panel->priv->data_dir = g_strdup (data_dir)g_strdup_inline (data_dir);
787
788 return GTK_WIDGET (panel)((((GtkWidget*) (void *) ((panel)))));
789}
790
791void
792_pluma_taglist_plugin_panel_register_type (GTypeModule *type_module)
793{
794 pluma_taglist_plugin_panel_register_type (type_module);
795}
diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-222690.html b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-222690.html new file mode 100644 index 00000000..f8bebede --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-222690.html @@ -0,0 +1,5495 @@ + + + +pluma-window.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:pluma/pluma-window.c
Warning:line 332, column 9
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pluma-window.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/pluma -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I .. -I . -I ./mate-submodules/libegg -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/gtksourceview-4 -I /usr/include/libpeas-1.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D DATADIR="/usr/local/share" -D PLUMA_DATADIR="/usr/local/share/pluma" -D PLUMA_LOCALEDIR="/usr/local/share/locale/" -D LIBDIR="/usr/local/lib" -D PLUMA_LIBDIR="/usr/local/lib/pluma" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/pluma -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-10-22-114445-13211-1 -x c pluma-window.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * pluma-window.c
3 * This file is part of pluma
4 *
5 * Copyright (C) 2005 - Paolo Maggi
6 * Copyright (C) 2012-2021 MATE Developers
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24/*
25 * Modified by the pluma Team, 2005. See the AUTHORS file for a
26 * list of people on the pluma Team.
27 * See the ChangeLog files for a list of changes.
28 *
29 * $Id$
30 */
31
32#ifdef HAVE_CONFIG_H1
33#include <config.h>
34#endif
35
36#include <time.h>
37#include <sys/types.h>
38#include <string.h>
39
40#include <gdk/gdk.h>
41#include <glib/gi18n.h>
42#include <gio/gio.h>
43#include <gtk/gtk.h>
44#include <gtksourceview/gtksource.h>
45#include <libpeas/peas-extension-set.h>
46
47#include "pluma-ui.h"
48#include "pluma-window.h"
49#include "pluma-window-private.h"
50#include "pluma-app.h"
51#include "pluma-notebook.h"
52#include "pluma-statusbar.h"
53#include "pluma-utils.h"
54#include "pluma-commands.h"
55#include "pluma-debug.h"
56#include "pluma-language-manager.h"
57#include "pluma-panel.h"
58#include "pluma-documents-panel.h"
59#include "pluma-plugins-engine.h"
60#include "pluma-window-activatable.h"
61#include "pluma-enum-types.h"
62#include "pluma-dirs.h"
63#include "pluma-status-combo-box.h"
64#include "pluma-settings.h"
65
66#define LANGUAGE_NONE(const gchar *)"LangNone" (const gchar *)"LangNone"
67#define TAB_WIDTH_DATA"PlumaWindowTabWidthData" "PlumaWindowTabWidthData"
68#define LANGUAGE_DATA"PlumaWindowLanguageData" "PlumaWindowLanguageData"
69#define FULLSCREEN_ANIMATION_SPEED4 4
70
71#define PLUMA_WINDOW_DEFAULT_WIDTH650 650
72#define PLUMA_WINDOW_DEFAULT_HEIGHT500 500
73
74/* Local variables */
75static gboolean cansave = TRUE(!(0));
76
77/* Signals */
78enum
79{
80 TAB_ADDED,
81 TAB_REMOVED,
82 TABS_REORDERED,
83 ACTIVE_TAB_CHANGED,
84 ACTIVE_TAB_STATE_CHANGED,
85 LAST_SIGNAL
86};
87
88static guint signals[LAST_SIGNAL] = { 0 };
89
90enum
91{
92 PROP_0,
93 PROP_STATE
94};
95
96enum
97{
98 TARGET_URI_LIST = 100
99};
100
101G_DEFINE_TYPE_WITH_PRIVATE (PlumaWindow, pluma_window, GTK_TYPE_WINDOW)static void pluma_window_init (PlumaWindow *self); static void
pluma_window_class_init (PlumaWindowClass *klass); static GType
pluma_window_get_type_once (void); static gpointer pluma_window_parent_class
= ((void*)0); static gint PlumaWindow_private_offset; static
void pluma_window_class_intern_init (gpointer klass) { pluma_window_parent_class
= g_type_class_peek_parent (klass); if (PlumaWindow_private_offset
!= 0) g_type_class_adjust_private_offset (klass, &PlumaWindow_private_offset
); pluma_window_class_init ((PlumaWindowClass*) klass); } __attribute__
((__unused__)) static inline gpointer pluma_window_get_instance_private
(PlumaWindow *self) { return (((gpointer) ((guint8*) (self) +
(glong) (PlumaWindow_private_offset)))); } GType pluma_window_get_type
(void) { static gsize static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) *(&static_g_define_type_id) : ((void*)0));
(!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id
)); }))) { GType g_define_type_id = pluma_window_get_type_once
(); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&static_g_define_type_id) = (g_define_type_id)
) : (void) 0; g_once_init_leave ((&static_g_define_type_id
), (gsize) (g_define_type_id)); })); } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType pluma_window_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_window_get_type ()), g_intern_static_string ("PlumaWindow"
), sizeof (PlumaWindowClass), (GClassInitFunc)(void (*)(void)
) pluma_window_class_intern_init, sizeof (PlumaWindow), (GInstanceInitFunc
)(void (*)(void)) pluma_window_init, (GTypeFlags) 0); { {{ PlumaWindow_private_offset
= g_type_add_instance_private (g_define_type_id, sizeof (PlumaWindowPrivate
)); };} } return g_define_type_id; }
102
103static void recent_manager_changed (GtkRecentManager *manager,
104 PlumaWindow *window);
105
106static void
107pluma_window_get_property (GObject *object,
108 guint prop_id,
109 GValue *value,
110 GParamSpec *pspec)
111{
112 PlumaWindow *window = PLUMA_WINDOW (object)((((PlumaWindow*) (void *) ((object)))));
113
114 switch (prop_id)
115 {
116 case PROP_STATE:
117 g_value_set_enum (value,
118 pluma_window_get_state (window));
119 break;
120 default:
121 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "pluma-window.c", 121, ("property"), _glib__property_id, _glib__pspec
->name, g_type_name ((((((GTypeClass*) (((GTypeInstance*) (
_glib__pspec))->g_class))->g_type)))), (g_type_name (((
(((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
122 break;
123 }
124}
125
126static void
127save_panes_state (PlumaWindow *window)
128{
129 gint pane_page;
130
131 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 131, ((const char*) (__func__
))
);
132
133 g_settings_set (window->priv->editor_settings, PLUMA_SETTINGS_WINDOW_SIZE"size",
134 "(ii)", window->priv->width, window->priv->height);
135
136 g_settings_set_int (window->priv->editor_settings, PLUMA_SETTINGS_WINDOW_STATE"state",
137 window->priv->window_state);
138
139 if (window->priv->side_panel_size > 0)
140 g_settings_set_int (window->priv->editor_settings,
141 PLUMA_SETTINGS_SIDE_PANEL_SIZE"side-panel-size",
142 window->priv->side_panel_size);
143
144 pane_page = _pluma_panel_get_active_item_id (PLUMA_PANEL (window->priv->side_panel)((((PlumaPanel*) (void *) ((window->priv->side_panel)))
))
);
145 if (pane_page != 0)
146 g_settings_set_int (window->priv->editor_settings,
147 PLUMA_SETTINGS_SIDE_PANEL_ACTIVE_PAGE"side-panel-active-page",
148 pane_page);
149
150 if (window->priv->bottom_panel_size > 0)
151 g_settings_set_int (window->priv->editor_settings,
152 PLUMA_SETTINGS_BOTTOM_PANEL_SIZE"bottom-panel-size",
153 window->priv->bottom_panel_size);
154
155 pane_page = _pluma_panel_get_active_item_id (PLUMA_PANEL (window->priv->bottom_panel)((((PlumaPanel*) (void *) ((window->priv->bottom_panel)
))))
);
156 if (pane_page != 0)
157 g_settings_set_int (window->priv->editor_settings,
158 PLUMA_SETTINGS_BOTTOM_PANEL_ACTIVE_PAGE"bottom-panel-active-page", pane_page);
159}
160
161static void
162pluma_window_dispose (GObject *object)
163{
164 PlumaWindow *window;
165
166 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 166, ((const char*) (__func__
))
);
167
168 window = PLUMA_WINDOW (object)((((PlumaWindow*) (void *) ((object)))));
169
170 /* Stop tracking removal of panes otherwise we always
171 * end up with thinking we had no pane active, since they
172 * should all be removed below */
173#if GLIB_CHECK_VERSION(2,62,0)(2 > (2) || (2 == (2) && 76 > (62)) || (2 == (2
) && 76 == (62) && 5 >= (0)))
174 g_clear_signal_handler (&window->priv->bottom_panel_item_removed_handler_id,do { gpointer const _instance = (window->priv->bottom_panel
); gulong *const _handler_id_ptr = (&window->priv->
bottom_panel_item_removed_handler_id); const gulong _handler_id
= *_handler_id_ptr; if (_handler_id > 0) { *_handler_id_ptr
= 0; g_signal_handler_disconnect (_instance, _handler_id); }
} while (0)
175 window->priv->bottom_panel)do { gpointer const _instance = (window->priv->bottom_panel
); gulong *const _handler_id_ptr = (&window->priv->
bottom_panel_item_removed_handler_id); const gulong _handler_id
= *_handler_id_ptr; if (_handler_id > 0) { *_handler_id_ptr
= 0; g_signal_handler_disconnect (_instance, _handler_id); }
} while (0)
;
176#else
177 if (window->priv->bottom_panel_item_removed_handler_id != 0)
178 {
179 g_signal_handler_disconnect (window->priv->bottom_panel,
180 window->priv->bottom_panel_item_removed_handler_id);
181 window->priv->bottom_panel_item_removed_handler_id = 0;
182 }
183#endif
184
185 /* First of all, force collection so that plugins
186 * really drop some of the references.
187 */
188 peas_engine_garbage_collect (PEAS_ENGINE (pluma_plugins_engine_get_default ())((((PeasEngine*) (void *) ((pluma_plugins_engine_get_default (
))))))
);
189
190 /* save the panes position and make sure to deactivate plugins
191 * for this window, but only once */
192 if (!window->priv->dispose_has_run)
193 {
194 save_panes_state (window);
195
196 /* Note that unreffing the extensions will automatically remove
197 all extensions which in turn will deactivate the extension */
198 g_object_unref (window->priv->extensions);
199
200 peas_engine_garbage_collect (PEAS_ENGINE (pluma_plugins_engine_get_default ())((((PeasEngine*) (void *) ((pluma_plugins_engine_get_default (
))))))
);
201
202 window->priv->dispose_has_run = TRUE(!(0));
203 }
204
205 if (window->priv->fullscreen_animation_timeout_id != 0)
206 {
207 g_source_remove (window->priv->fullscreen_animation_timeout_id);
208 window->priv->fullscreen_animation_timeout_id = 0;
209 }
210
211 if (window->priv->fullscreen_controls != NULL((void*)0))
212 {
213 gtk_widget_destroy (window->priv->fullscreen_controls);
214
215 window->priv->fullscreen_controls = NULL((void*)0);
216 }
217
218 if (window->priv->recents_handler_id != 0)
219 {
220 GtkRecentManager *recent_manager;
221
222 recent_manager = gtk_recent_manager_get_default ();
223#if GLIB_CHECK_VERSION(2,62,0)(2 > (2) || (2 == (2) && 76 > (62)) || (2 == (2
) && 76 == (62) && 5 >= (0)))
224 g_clear_signal_handler (&window->priv->recents_handler_id,do { gpointer const _instance = (recent_manager); gulong *const
_handler_id_ptr = (&window->priv->recents_handler_id
); const gulong _handler_id = *_handler_id_ptr; if (_handler_id
> 0) { *_handler_id_ptr = 0; g_signal_handler_disconnect (
_instance, _handler_id); } } while (0)
225 recent_manager)do { gpointer const _instance = (recent_manager); gulong *const
_handler_id_ptr = (&window->priv->recents_handler_id
); const gulong _handler_id = *_handler_id_ptr; if (_handler_id
> 0) { *_handler_id_ptr = 0; g_signal_handler_disconnect (
_instance, _handler_id); } } while (0)
;
226#else
227 g_signal_handler_disconnect (recent_manager,
228 window->priv->recents_handler_id);
229 window->priv->recents_handler_id = 0;
230#endif
231 }
232
233 if (window->priv->manager != NULL((void*)0))
234 {
235 g_object_unref (window->priv->manager);
236 window->priv->manager = NULL((void*)0);
237 }
238
239 if (window->priv->message_bus != NULL((void*)0))
240 {
241 g_object_unref (window->priv->message_bus);
242 window->priv->message_bus = NULL((void*)0);
243 }
244
245 if (window->priv->window_group != NULL((void*)0))
246 {
247 g_object_unref (window->priv->window_group);
248 window->priv->window_group = NULL((void*)0);
249 }
250
251 /* We must free the settings after saving the panels */
252 g_clear_object (&window->priv->editor_settings)do { _Static_assert (sizeof *((&window->priv->editor_settings
)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(((&window->priv->editor_settings))) _pp = ((&
window->priv->editor_settings)); __typeof__ (*((&window
->priv->editor_settings))) _ptr = *_pp; *_pp = ((void*)
0); if (_ptr) (g_object_unref) (_ptr); } while (0)
;
253
254 /* Now that there have broken some reference loops,
255 * force collection again.
256 */
257 peas_engine_garbage_collect (PEAS_ENGINE (pluma_plugins_engine_get_default ())((((PeasEngine*) (void *) ((pluma_plugins_engine_get_default (
))))))
);
258
259 G_OBJECT_CLASS (pluma_window_parent_class)((((GObjectClass*) (void *) ((pluma_window_parent_class)))))->dispose (object);
260}
261
262static void
263pluma_window_finalize (GObject *object)
264{
265 PlumaWindow *window;
266
267 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 267, ((const char*) (__func__
))
);
268
269 window = PLUMA_WINDOW (object)((((PlumaWindow*) (void *) ((object)))));
270
271 if (window->priv->default_location != NULL((void*)0))
272 g_object_unref (window->priv->default_location);
273
274 G_OBJECT_CLASS (pluma_window_parent_class)((((GObjectClass*) (void *) ((pluma_window_parent_class)))))->finalize (object);
275}
276
277static gboolean
278pluma_window_window_state_event (GtkWidget *widget,
279 GdkEventWindowState *event)
280{
281 PlumaWindow *window = PLUMA_WINDOW (widget)((((PlumaWindow*) (void *) ((widget)))));
282
283 window->priv->window_state = event->new_window_state;
284
285 return GTK_WIDGET_CLASS (pluma_window_parent_class)((((GtkWidgetClass*) (void *) ((pluma_window_parent_class))))
)
->window_state_event (widget, event);
286}
287
288static gboolean
289pluma_window_configure_event (GtkWidget *widget,
290 GdkEventConfigure *event)
291{
292 PlumaWindow *window = PLUMA_WINDOW (widget)((((PlumaWindow*) (void *) ((widget)))));
293
294 window->priv->width = event->width;
295 window->priv->height = event->height;
296
297 return GTK_WIDGET_CLASS (pluma_window_parent_class)((((GtkWidgetClass*) (void *) ((pluma_window_parent_class))))
)
->configure_event (widget, event);
298}
299
300/*
301 * GtkWindow catches keybindings for the menu items _before_ passing them to
302 * the focused widget. This is unfortunate and means that pressing ctrl+V
303 * in an entry on a panel ends up pasting text in the TextView.
304 * Here we override GtkWindow's handler to do the same things that it
305 * does, but in the opposite order and then we chain up to the grand
306 * parent handler, skipping gtk_window_key_press_event.
307 */
308static gboolean
309pluma_window_key_press_event (GtkWidget *widget,
310 GdkEventKey *event)
311{
312 static gpointer grand_parent_class = NULL((void*)0);
313 GtkWindow *window = GTK_WINDOW (widget)((((GtkWindow*) (void *) ((widget)))));
314 gboolean handled = FALSE(0);
315 /* FIXME: avoid making a new gsettings variable here */
316 GSettings *settings = g_settings_new (PLUMA_SCHEMA_ID"org.mate.pluma");
317
318 if (event->state & GDK_CONTROL_MASK)
319 {
320 gchar *font;
321 gchar *tempsize;
322 gint nsize;
323
324 font = g_settings_get_string (settings, PLUMA_SETTINGS_EDITOR_FONT"editor-font");
325 tempsize = g_strdup (font)g_strdup_inline (font);
326
327 g_strreverse (tempsize);
328 g_strcanon (tempsize, "1234567890", '\0');
329 g_strreverse (tempsize);
330
331 gchar tempfont [strlen (font) + 1];
332 strcpy (tempfont, font);
Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119
333 tempfont [strlen (font) - strlen (tempsize)] = 0;
334
335 sscanf (tempsize, "%d", &nsize);
336
337 if ((event->keyval == GDK_KEY_plus0x02b) || (event->keyval == GDK_KEY_KP_Add0xffab))
338 {
339 nsize = nsize + 1;
340 sprintf (tempsize, "%d", nsize);
341
342 if (!g_settings_get_boolean (settings, PLUMA_SETTINGS_USE_DEFAULT_FONT"use-default-font") && (nsize < 73))
343 {
344 gchar *tmp = g_strconcat (tempfont, tempsize, NULL((void*)0));
345 g_settings_set_string (settings, PLUMA_SETTINGS_EDITOR_FONT"editor-font", tmp);
346 g_free (tmp);
347 }
348 }
349 else if ((event->keyval == GDK_KEY_minus0x02d) || (event->keyval == GDK_KEY_KP_Subtract0xffad))
350 {
351 nsize = nsize - 1;
352 sprintf (tempsize, "%d", nsize);
353
354 if (!g_settings_get_boolean (settings, PLUMA_SETTINGS_USE_DEFAULT_FONT"use-default-font") && (nsize > 5))
355 {
356 gchar *tmp = g_strconcat (tempfont, tempsize, NULL((void*)0));
357 g_settings_set_string (settings, PLUMA_SETTINGS_EDITOR_FONT"editor-font", tmp);
358 g_free (tmp);
359 }
360 }
361 else if (event->keyval == GDK_KEY_y0x079)
362 {
363 g_settings_set_boolean (settings, PLUMA_SETTINGS_DISPLAY_LINE_NUMBERS"display-line-numbers",
364 !g_settings_get_boolean (settings, PLUMA_SETTINGS_DISPLAY_LINE_NUMBERS"display-line-numbers"));
365 }
366
367 if (g_settings_get_boolean (settings, PLUMA_SETTINGS_CTRL_TABS_SWITCH_TABS"ctrl-tab-switch-tabs"))
368 {
369 GtkNotebook *notebook = GTK_NOTEBOOK (_pluma_window_get_notebook (PLUMA_WINDOW (window)))((((GtkNotebook*) (void *) ((_pluma_window_get_notebook (((((
PlumaWindow*) (void *) ((window)))))))))))
;
370
371 int pages = gtk_notebook_get_n_pages (notebook);
372 int page_num = gtk_notebook_get_current_page (notebook);
373
374 if (event->keyval == GDK_KEY_ISO_Left_Tab0xfe20)
375 {
376 if (page_num != 0)
377 gtk_notebook_prev_page (notebook);
378 else
379 gtk_notebook_set_current_page (notebook, (pages - 1));
380 handled = TRUE(!(0));
381 }
382
383 if (event->keyval == GDK_KEY_Tab0xff09)
384 {
385 if (page_num != (pages -1))
386 gtk_notebook_next_page (notebook);
387 else
388 gtk_notebook_set_current_page (notebook, 0);
389 handled = TRUE(!(0));
390 }
391 }
392 g_free (font);
393 g_free (tempsize);
394 }
395
396 g_object_unref (settings);
397
398 if (grand_parent_class == NULL((void*)0))
399 grand_parent_class = g_type_class_peek_parent (pluma_window_parent_class);
400
401 /* handle focus widget key events */
402 if (!handled)
403 handled = gtk_window_propagate_key_event (window, event);
404
405 /* handle mnemonics and accelerators */
406 if (!handled)
407 handled = gtk_window_activate_key (window, event);
408
409 /* Chain up, invokes binding set */
410 if (!handled)
411 handled = GTK_WIDGET_CLASS (grand_parent_class)((((GtkWidgetClass*) (void *) ((grand_parent_class)))))->key_press_event (widget, event);
412
413 return handled;
414}
415
416static void
417pluma_window_tab_removed (PlumaWindow *window,
418 PlumaTab *tab)
419{
420 peas_engine_garbage_collect (PEAS_ENGINE (pluma_plugins_engine_get_default ())((((PeasEngine*) (void *) ((pluma_plugins_engine_get_default (
))))))
);
421}
422
423static void
424pluma_window_class_init (PlumaWindowClass *klass)
425{
426 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) ((klass)))));
427 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass)((((GtkWidgetClass*) (void *) ((klass)))));
428
429 klass->tab_removed = pluma_window_tab_removed;
430
431 object_class->dispose = pluma_window_dispose;
432 object_class->finalize = pluma_window_finalize;
433 object_class->get_property = pluma_window_get_property;
434
435 widget_class->window_state_event = pluma_window_window_state_event;
436 widget_class->configure_event = pluma_window_configure_event;
437 widget_class->key_press_event = pluma_window_key_press_event;
438
439 signals[TAB_ADDED] =
440 g_signal_new ("tab_added",
441 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
442 G_SIGNAL_RUN_FIRST,
443 G_STRUCT_OFFSET (PlumaWindowClass, tab_added)((glong) __builtin_offsetof(PlumaWindowClass, tab_added)),
444 NULL((void*)0), NULL((void*)0), NULL((void*)0),
445 G_TYPE_NONE((GType) ((1) << (2))),
446 1,
447 PLUMA_TYPE_TAB(pluma_tab_get_type()));
448 signals[TAB_REMOVED] =
449 g_signal_new ("tab_removed",
450 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
451 G_SIGNAL_RUN_FIRST,
452 G_STRUCT_OFFSET (PlumaWindowClass, tab_removed)((glong) __builtin_offsetof(PlumaWindowClass, tab_removed)),
453 NULL((void*)0), NULL((void*)0), NULL((void*)0),
454 G_TYPE_NONE((GType) ((1) << (2))),
455 1,
456 PLUMA_TYPE_TAB(pluma_tab_get_type()));
457 signals[TABS_REORDERED] =
458 g_signal_new ("tabs_reordered",
459 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
460 G_SIGNAL_RUN_FIRST,
461 G_STRUCT_OFFSET (PlumaWindowClass, tabs_reordered)((glong) __builtin_offsetof(PlumaWindowClass, tabs_reordered)
)
,
462 NULL((void*)0), NULL((void*)0), NULL((void*)0),
463 G_TYPE_NONE((GType) ((1) << (2))),
464 0);
465 signals[ACTIVE_TAB_CHANGED] =
466 g_signal_new ("active_tab_changed",
467 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
468 G_SIGNAL_RUN_FIRST,
469 G_STRUCT_OFFSET (PlumaWindowClass, active_tab_changed)((glong) __builtin_offsetof(PlumaWindowClass, active_tab_changed
))
,
470 NULL((void*)0), NULL((void*)0), NULL((void*)0),
471 G_TYPE_NONE((GType) ((1) << (2))),
472 1,
473 PLUMA_TYPE_TAB(pluma_tab_get_type()));
474 signals[ACTIVE_TAB_STATE_CHANGED] =
475 g_signal_new ("active_tab_state_changed",
476 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
477 G_SIGNAL_RUN_FIRST,
478 G_STRUCT_OFFSET (PlumaWindowClass, active_tab_state_changed)((glong) __builtin_offsetof(PlumaWindowClass, active_tab_state_changed
))
,
479 NULL((void*)0), NULL((void*)0), NULL((void*)0),
480 G_TYPE_NONE((GType) ((1) << (2))),
481 0);
482
483 g_object_class_install_property (object_class,
484 PROP_STATE,
485 g_param_spec_flags ("state",
486 "State",
487 "The window's state",
488 PLUMA_TYPE_WINDOW_STATE(pluma_window_state_get_type()),
489 PLUMA_WINDOW_STATE_NORMAL,
490 G_PARAM_READABLE |
491 G_PARAM_STATIC_STRINGS(G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB
)
));
492}
493
494static void
495menu_item_select_cb (GtkMenuItem *proxy,
496 PlumaWindow *window)
497{
498 GtkAction *action;
499 char *message;
500
501 action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (proxy)((((GtkActivatable*) (void *) ((proxy))))));
502 g_return_if_fail (action != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_67
; if (action != ((void*)0)) _g_boolean_var_67 = 1; else _g_boolean_var_67
= 0; _g_boolean_var_67; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "action != NULL")
; return; } } while (0)
;
503
504 g_object_get (G_OBJECT (action)((((GObject*) (void *) ((action))))), "tooltip", &message, NULL((void*)0));
505 if (message)
506 {
507 gtk_statusbar_push (GTK_STATUSBAR (window->priv->statusbar)((((GtkStatusbar*) (void *) ((window->priv->statusbar))
)))
,
508 window->priv->tip_message_cid, message);
509 g_free (message);
510 }
511}
512
513static void
514menu_item_deselect_cb (GtkMenuItem *proxy,
515 PlumaWindow *window)
516{
517 gtk_statusbar_pop (GTK_STATUSBAR (window->priv->statusbar)((((GtkStatusbar*) (void *) ((window->priv->statusbar))
)))
,
518 window->priv->tip_message_cid);
519}
520
521static void
522connect_proxy_cb (GtkUIManager *manager,
523 GtkAction *action,
524 GtkWidget *proxy,
525 PlumaWindow *window)
526{
527 if (GTK_IS_MENU_ITEM (proxy)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(proxy)); GType __t = ((gtk_menu_item_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
528 {
529 g_signal_connect (proxy, "select",g_signal_connect_data ((proxy), ("select"), (((GCallback) (menu_item_select_cb
))), (window), ((void*)0), (GConnectFlags) 0)
530 G_CALLBACK (menu_item_select_cb), window)g_signal_connect_data ((proxy), ("select"), (((GCallback) (menu_item_select_cb
))), (window), ((void*)0), (GConnectFlags) 0)
;
531 g_signal_connect (proxy, "deselect",g_signal_connect_data ((proxy), ("deselect"), (((GCallback) (
menu_item_deselect_cb))), (window), ((void*)0), (GConnectFlags
) 0)
532 G_CALLBACK (menu_item_deselect_cb), window)g_signal_connect_data ((proxy), ("deselect"), (((GCallback) (
menu_item_deselect_cb))), (window), ((void*)0), (GConnectFlags
) 0)
;
533 }
534}
535
536static void
537disconnect_proxy_cb (GtkUIManager *manager,
538 GtkAction *action,
539 GtkWidget *proxy,
540 PlumaWindow *window)
541{
542 if (GTK_IS_MENU_ITEM (proxy)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(proxy)); GType __t = ((gtk_menu_item_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
543 {
544 g_signal_handlers_disconnect_by_funcg_signal_handlers_disconnect_matched ((proxy), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (menu_item_select_cb))), (window))
545 (proxy, G_CALLBACK (menu_item_select_cb), window)g_signal_handlers_disconnect_matched ((proxy), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (menu_item_select_cb))), (window))
;
546 g_signal_handlers_disconnect_by_funcg_signal_handlers_disconnect_matched ((proxy), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (menu_item_deselect_cb))), (window))
547 (proxy, G_CALLBACK (menu_item_deselect_cb), window)g_signal_handlers_disconnect_matched ((proxy), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (menu_item_deselect_cb))), (window))
;
548 }
549}
550
551static void
552apply_toolbar_style (PlumaWindow *window,
553 GtkWidget *toolbar)
554{
555 switch (window->priv->toolbar_style)
556 {
557 case PLUMA_TOOLBAR_SYSTEM:
558 pluma_debug_message (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 558, ((const char*) (__func__
))
, "PLUMA: SYSTEM");
559 gtk_toolbar_unset_style (GTK_TOOLBAR (toolbar)((((GtkToolbar*) (void *) ((toolbar))))));
560 break;
561
562 case PLUMA_TOOLBAR_ICONS:
563 pluma_debug_message (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 563, ((const char*) (__func__
))
, "PLUMA: ICONS");
564 gtk_toolbar_set_style (GTK_TOOLBAR (toolbar)((((GtkToolbar*) (void *) ((toolbar))))),
565 GTK_TOOLBAR_ICONS);
566 break;
567
568 case PLUMA_TOOLBAR_ICONS_AND_TEXT:
569 pluma_debug_message (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 569, ((const char*) (__func__
))
, "PLUMA: ICONS_AND_TEXT");
570 gtk_toolbar_set_style (GTK_TOOLBAR (toolbar)((((GtkToolbar*) (void *) ((toolbar))))),
571 GTK_TOOLBAR_BOTH);
572 break;
573
574 case PLUMA_TOOLBAR_ICONS_BOTH_HORIZ:
575 pluma_debug_message (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 575, ((const char*) (__func__
))
, "PLUMA: ICONS_BOTH_HORIZ");
576 gtk_toolbar_set_style (GTK_TOOLBAR (toolbar)((((GtkToolbar*) (void *) ((toolbar))))),
577 GTK_TOOLBAR_BOTH_HORIZ);
578 break;
579 }
580}
581
582/* Returns TRUE if toolbar is visible */
583static gboolean
584set_toolbar_style (PlumaWindow *window,
585 PlumaWindow *origin)
586{
587 gboolean visible;
588 PlumaToolbarSetting style;
589 GtkAction *action;
590
591 if (origin == NULL((void*)0))
592 visible = g_settings_get_boolean (window->priv->editor_settings,
593 PLUMA_SETTINGS_TOOLBAR_VISIBLE"toolbar-visible");
594 else
595 visible = gtk_widget_get_visible (origin->priv->toolbar);
596
597 /* Set visibility */
598 if (visible)
599 gtk_widget_show (window->priv->toolbar);
600 else
601 gtk_widget_hide (window->priv->toolbar);
602
603 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group,
604 "ViewToolbar");
605
606 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action)))))) != visible)
607 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action))))), visible);
608
609 /* Set style */
610 if (origin == NULL((void*)0))
611 {
612 PlumaSettings *settings;
613
614 settings = _pluma_settings_get_singleton ();
615 style = pluma_settings_get_toolbar_style (settings);
616 }
617 else
618 {
619 style = origin->priv->toolbar_style;
620 }
621
622 window->priv->toolbar_style = style;
623
624 apply_toolbar_style (window, window->priv->toolbar);
625
626 return visible;
627}
628
629static void
630update_next_prev_doc_sensitivity (PlumaWindow *window,
631 PlumaTab *tab)
632{
633 gint tab_number;
634 GtkNotebook *notebook;
635 GtkAction *action;
636
637 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 637, ((const char*) (__func__
))
);
638
639 notebook = GTK_NOTEBOOK (_pluma_window_get_notebook (window))((((GtkNotebook*) (void *) ((_pluma_window_get_notebook (window
))))))
;
640
641 tab_number = gtk_notebook_page_num (notebook, GTK_WIDGET (tab)((((GtkWidget*) (void *) ((tab))))));
642 g_return_if_fail (tab_number >= 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_68
; if (tab_number >= 0) _g_boolean_var_68 = 1; else _g_boolean_var_68
= 0; _g_boolean_var_68; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "tab_number >= 0"
); return; } } while (0)
;
643
644 action = gtk_action_group_get_action (window->priv->action_group,
645 "DocumentsPreviousDocument");
646 gtk_action_set_sensitive (action, tab_number != 0);
647
648 action = gtk_action_group_get_action (window->priv->action_group,
649 "DocumentsNextDocument");
650 gtk_action_set_sensitive (action,
651 tab_number < gtk_notebook_get_n_pages (notebook) - 1);
652}
653
654static void
655update_next_prev_doc_sensitivity_per_window (PlumaWindow *window)
656{
657 PlumaTab *tab;
658 GtkAction *action;
659
660 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 660, ((const char*) (__func__
))
);
661
662 tab = pluma_window_get_active_tab (window);
663 if (tab != NULL((void*)0))
664 {
665 update_next_prev_doc_sensitivity (window, tab);
666
667 return;
668 }
669
670 action = gtk_action_group_get_action (window->priv->action_group,
671 "DocumentsPreviousDocument");
672 gtk_action_set_sensitive (action, FALSE(0));
673
674 action = gtk_action_group_get_action (window->priv->action_group,
675 "DocumentsNextDocument");
676 gtk_action_set_sensitive (action, FALSE(0));
677
678}
679
680static void
681received_clipboard_contents (GtkClipboard *clipboard,
682 GtkSelectionData *selection_data,
683 PlumaWindow *window)
684{
685 gboolean sens;
686 GtkAction *action;
687
688 /* getting clipboard contents is async, so we need to
689 * get the current tab and its state */
690
691 if (window->priv->active_tab != NULL((void*)0))
692 {
693 PlumaTabState state;
694 gboolean state_normal;
695
696 state = pluma_tab_get_state (window->priv->active_tab);
697 state_normal = (state == PLUMA_TAB_STATE_NORMAL);
698
699 sens = state_normal &&
700 gtk_selection_data_targets_include_text (selection_data);
701 }
702 else
703 {
704 sens = FALSE(0);
705 }
706
707 action = gtk_action_group_get_action (window->priv->action_group, "EditPaste");
708
709 gtk_action_set_sensitive (action, sens);
710
711 g_object_unref (window);
712}
713
714static void
715set_paste_sensitivity_according_to_clipboard (PlumaWindow *window,
716 GtkClipboard *clipboard)
717{
718 GdkDisplay *display;
719
720 display = gtk_clipboard_get_display (clipboard);
721
722 if (gdk_display_supports_selection_notification (display))
723 {
724 gtk_clipboard_request_contents (clipboard,
725 gdk_atom_intern_static_string ("TARGETS"),
726 (GtkClipboardReceivedFunc) received_clipboard_contents,
727 g_object_ref (window)((__typeof__ (window)) (g_object_ref) (window)));
728 }
729 else
730 {
731 GtkAction *action;
732
733 action = gtk_action_group_get_action (window->priv->action_group,
734 "EditPaste");
735
736 /* XFIXES extension not availbale, make
737 * Paste always sensitive */
738 gtk_action_set_sensitive (action, TRUE(!(0)));
739 }
740}
741
742static void
743set_sensitivity_according_to_tab (PlumaWindow *window,
744 PlumaTab *tab)
745{
746 PlumaDocument *doc;
747 PlumaView *view;
748 GtkAction *action;
749 gboolean b;
750 gboolean state_normal;
751 gboolean editable;
752 PlumaTabState state;
753 GtkClipboard *clipboard;
754 PlumaLockdownMask lockdown;
755 gboolean enable_syntax_highlighting;
756
757 g_return_if_fail (PLUMA_TAB (tab))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_69
; if (((((PlumaTab*) (void *) ((tab)))))) _g_boolean_var_69 =
1; else _g_boolean_var_69 = 0; _g_boolean_var_69; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "PLUMA_TAB (tab)"); return; } } while (0)
;
758
759 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 759, ((const char*) (__func__
))
);
760
761 enable_syntax_highlighting = g_settings_get_boolean (window->priv->editor_settings,
762 PLUMA_SETTINGS_SYNTAX_HIGHLIGHTING"syntax-highlighting");
763
764 lockdown = pluma_app_get_lockdown (pluma_app_get_default ());
765
766 state = pluma_tab_get_state (tab);
767 state_normal = (state == PLUMA_TAB_STATE_NORMAL);
768
769 view = pluma_tab_get_view (tab);
770 editable = gtk_text_view_get_editable (GTK_TEXT_VIEW (view)((((GtkTextView*) (void *) ((view))))));
771
772 doc = PLUMA_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)))((((PlumaDocument*) (void *) ((gtk_text_view_get_buffer (((((
GtkTextView*) (void *) ((view)))))))))))
;
773
774 clipboard = gtk_widget_get_clipboard (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))),
775 GDK_SELECTION_CLIPBOARD((GdkAtom)((gpointer) (gulong) (69))));
776
777 action = gtk_action_group_get_action (window->priv->action_group,
778 "FileSave");
779
780 if (state == PLUMA_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) {
781 gtk_text_buffer_set_modified (GTK_TEXT_BUFFER (doc)((((GtkTextBuffer*) (void *) ((doc))))), TRUE(!(0)));
782 }
783
784 gtk_action_set_sensitive (action,
785 (state_normal ||
786 (state == PLUMA_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) ||
787 (state == PLUMA_TAB_STATE_SHOWING_PRINT_PREVIEW)) &&
788 !pluma_document_get_readonly (doc) &&
789 !(lockdown & PLUMA_LOCKDOWN_SAVE_TO_DISK) &&
790 (cansave) &&
791 (editable));
792
793 action = gtk_action_group_get_action (window->priv->action_group,
794 "FileSaveAs");
795 gtk_action_set_sensitive (action,
796 (state_normal ||
797 (state == PLUMA_TAB_STATE_SAVING_ERROR) ||
798 (state == PLUMA_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) ||
799 (state == PLUMA_TAB_STATE_SHOWING_PRINT_PREVIEW)) &&
800 !(lockdown & PLUMA_LOCKDOWN_SAVE_TO_DISK));
801
802 action = gtk_action_group_get_action (window->priv->action_group,
803 "FileRevert");
804 gtk_action_set_sensitive (action,
805 (state_normal ||
806 (state == PLUMA_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION)) &&
807 !pluma_document_is_untitled (doc));
808
809 action = gtk_action_group_get_action (window->priv->action_group,
810 "FilePrintPreview");
811 gtk_action_set_sensitive (action,
812 state_normal &&
813 !(lockdown & PLUMA_LOCKDOWN_PRINTING));
814
815 action = gtk_action_group_get_action (window->priv->action_group,
816 "FilePrint");
817 gtk_action_set_sensitive (action,
818 (state_normal ||
819 (state == PLUMA_TAB_STATE_SHOWING_PRINT_PREVIEW)) &&
820 !(lockdown & PLUMA_LOCKDOWN_PRINTING));
821
822 action = gtk_action_group_get_action (window->priv->close_action_group,
823 "FileClose");
824
825 gtk_action_set_sensitive (action,
826 (state != PLUMA_TAB_STATE_CLOSING) &&
827 (state != PLUMA_TAB_STATE_SAVING) &&
828 (state != PLUMA_TAB_STATE_SHOWING_PRINT_PREVIEW) &&
829 (state != PLUMA_TAB_STATE_PRINTING) &&
830 (state != PLUMA_TAB_STATE_PRINT_PREVIEWING) &&
831 (state != PLUMA_TAB_STATE_SAVING_ERROR));
832
833 action = gtk_action_group_get_action (window->priv->action_group,
834 "EditUndo");
835 gtk_action_set_sensitive (action,
836 state_normal &&
837 gtk_source_buffer_can_undo (GTK_SOURCE_BUFFER (doc)((((GtkSourceBuffer*) (void *) ((doc)))))));
838
839 action = gtk_action_group_get_action (window->priv->action_group,
840 "EditRedo");
841 gtk_action_set_sensitive (action,
842 state_normal &&
843 gtk_source_buffer_can_redo (GTK_SOURCE_BUFFER (doc)((((GtkSourceBuffer*) (void *) ((doc)))))));
844
845 action = gtk_action_group_get_action (window->priv->action_group,
846 "EditCut");
847 gtk_action_set_sensitive (action,
848 state_normal &&
849 editable &&
850 gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (doc)((((GtkTextBuffer*) (void *) ((doc)))))));
851
852 action = gtk_action_group_get_action (window->priv->action_group,
853 "EditCopy");
854 gtk_action_set_sensitive (action,
855 (state_normal ||
856 state == PLUMA_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) &&
857 gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (doc)((((GtkTextBuffer*) (void *) ((doc)))))));
858
859 action = gtk_action_group_get_action (window->priv->action_group,
860 "EditPaste");
861 if (state_normal && editable)
862 {
863 set_paste_sensitivity_according_to_clipboard (window, clipboard);
864 }
865 else
866 {
867 gtk_action_set_sensitive (action, FALSE(0));
868 }
869
870 action = gtk_action_group_get_action (window->priv->action_group,
871 "EditDelete");
872 gtk_action_set_sensitive (action,
873 state_normal &&
874 editable &&
875 gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (doc)((((GtkTextBuffer*) (void *) ((doc)))))));
876
877 action = gtk_action_group_get_action (window->priv->action_group,
878 "SearchFind");
879 gtk_action_set_sensitive (action,
880 (state_normal ||
881 state == PLUMA_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION));
882
883 action = gtk_action_group_get_action (window->priv->action_group,
884 "SearchIncrementalSearch");
885 gtk_action_set_sensitive (action,
886 (state_normal ||
887 state == PLUMA_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION));
888
889 action = gtk_action_group_get_action (window->priv->action_group,
890 "SearchReplace");
891 gtk_action_set_sensitive (action,
892 state_normal &&
893 editable);
894
895 b = pluma_document_get_can_search_again (doc);
896 action = gtk_action_group_get_action (window->priv->action_group,
897 "SearchFindNext");
898 gtk_action_set_sensitive (action,
899 (state_normal ||
900 state == PLUMA_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) && b);
901
902 action = gtk_action_group_get_action (window->priv->action_group,
903 "SearchFindPrevious");
904 gtk_action_set_sensitive (action,
905 (state_normal ||
906 state == PLUMA_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) && b);
907
908 action = gtk_action_group_get_action (window->priv->action_group,
909 "SearchClearHighlight");
910 gtk_action_set_sensitive (action,
911 (state_normal ||
912 state == PLUMA_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) && b);
913
914 action = gtk_action_group_get_action (window->priv->action_group,
915 "SearchGoToLine");
916 gtk_action_set_sensitive (action,
917 (state_normal ||
918 state == PLUMA_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION));
919
920 action = gtk_action_group_get_action (window->priv->action_group,
921 "ViewHighlightMode");
922 gtk_action_set_sensitive (action,
923 (state != PLUMA_TAB_STATE_CLOSING) &&
924 enable_syntax_highlighting);
925
926 update_next_prev_doc_sensitivity (window, tab);
927
928 peas_extension_set_call (window->priv->extensions, "update_state");
929}
930
931static void
932language_toggled (GtkToggleAction *action,
933 PlumaWindow *window)
934{
935 PlumaDocument *doc;
936 GtkSourceLanguage *lang;
937 const gchar *lang_id;
938
939 if (gtk_toggle_action_get_active (action) == FALSE(0))
940 return;
941
942 doc = pluma_window_get_active_document (window);
943 if (doc == NULL((void*)0))
944 return;
945
946 lang_id = gtk_action_get_name (GTK_ACTION (action)((((GtkAction*) (void *) ((action))))));
947
948 if (strcmp (lang_id, LANGUAGE_NONE(const gchar *)"LangNone") == 0)
949 {
950 /* Normal (no highlighting) */
951 lang = NULL((void*)0);
952 }
953 else
954 {
955 lang = gtk_source_language_manager_get_language (pluma_get_language_manager (),
956 lang_id);
957 if (lang == NULL((void*)0))
958 {
959 g_warning ("Could not get language %s\n", lang_id);
960 }
961 }
962
963 pluma_document_set_language (doc, lang);
964}
965
966static gchar *
967escape_section_name (const gchar *name)
968{
969 gchar *ret;
970
971 ret = g_markup_escape_text (name, -1);
972
973 /* Replace '/' with '-' to avoid problems in xml paths */
974 g_strdelimit (ret, "/", '-');
975
976 return ret;
977}
978
979static void
980create_language_menu_item (GtkSourceLanguage *lang,
981 gint index,
982 guint ui_id,
983 PlumaWindow *window)
984{
985 GtkAction *section_action;
986 GtkRadioAction *action;
987 GtkAction *normal_action;
988 GSList *group;
989 const gchar *section;
990 gchar *escaped_section;
991 const gchar *lang_id;
992 const gchar *lang_name;
993 gchar *escaped_lang_name;
994 gchar *tip;
995 gchar *path;
996
997 section = gtk_source_language_get_section (lang);
998 escaped_section = escape_section_name (section);
999
1000 /* check if the section submenu exists or create it */
1001 section_action = gtk_action_group_get_action (window->priv->languages_action_group,
1002 escaped_section);
1003
1004 if (section_action == NULL((void*)0))
1005 {
1006 gchar *section_name;
1007
1008 section_name = pluma_utils_escape_underscores (section, -1);
1009
1010 section_action = gtk_action_new (escaped_section,
1011 section_name,
1012 NULL((void*)0),
1013 NULL((void*)0));
1014
1015 g_free (section_name);
1016
1017 gtk_action_group_add_action (window->priv->languages_action_group,
1018 section_action);
1019 g_object_unref (section_action);
1020
1021 gtk_ui_manager_add_ui (window->priv->manager,
1022 ui_id,
1023 "/MenuBar/ViewMenu/ViewHighlightModeMenu/LanguagesMenuPlaceholder",
1024 escaped_section,
1025 escaped_section,
1026 GTK_UI_MANAGER_MENU,
1027 FALSE(0));
1028 }
1029
1030 /* now add the language item to the section */
1031 lang_name = gtk_source_language_get_name (lang);
1032 lang_id = gtk_source_language_get_id (lang);
1033
1034 escaped_lang_name = pluma_utils_escape_underscores (lang_name, -1);
1035
1036 tip = g_strdup_printf (_("Use %s highlight mode")dcgettext (((void*)0), "Use %s highlight mode", 5), lang_name);
1037 path = g_strdup_printf ("/MenuBar/ViewMenu/ViewHighlightModeMenu/LanguagesMenuPlaceholder/%s",
1038 escaped_section);
1039
1040 action = gtk_radio_action_new (lang_id,
1041 escaped_lang_name,
1042 tip,
1043 NULL((void*)0),
1044 index);
1045
1046 g_free (escaped_lang_name);
1047
1048 /* Action is added with a NULL accel to make the accel overridable */
1049 gtk_action_group_add_action_with_accel (window->priv->languages_action_group,
1050 GTK_ACTION (action)((((GtkAction*) (void *) ((action))))),
1051 NULL((void*)0));
1052 g_object_unref (action);
1053
1054 /* add the action to the same radio group of the "Normal" action */
1055 normal_action = gtk_action_group_get_action (window->priv->languages_action_group,
1056 LANGUAGE_NONE(const gchar *)"LangNone");
1057 group = gtk_radio_action_get_group (GTK_RADIO_ACTION (normal_action)((((GtkRadioAction*) (void *) ((normal_action))))));
1058 gtk_radio_action_set_group (action, group);
1059
1060 g_signal_connect (action,g_signal_connect_data ((action), ("activate"), (((GCallback) (
language_toggled))), (window), ((void*)0), (GConnectFlags) 0)
1061 "activate",g_signal_connect_data ((action), ("activate"), (((GCallback) (
language_toggled))), (window), ((void*)0), (GConnectFlags) 0)
1062 G_CALLBACK (language_toggled),g_signal_connect_data ((action), ("activate"), (((GCallback) (
language_toggled))), (window), ((void*)0), (GConnectFlags) 0)
1063 window)g_signal_connect_data ((action), ("activate"), (((GCallback) (
language_toggled))), (window), ((void*)0), (GConnectFlags) 0)
;
1064
1065 gtk_ui_manager_add_ui (window->priv->manager,
1066 ui_id,
1067 path,
1068 lang_id,
1069 lang_id,
1070 GTK_UI_MANAGER_MENUITEM,
1071 FALSE(0));
1072
1073 g_free (path);
1074 g_free (tip);
1075 g_free (escaped_section);
1076}
1077
1078static void
1079create_languages_menu (PlumaWindow *window)
1080{
1081 GtkRadioAction *action_none;
1082 GSList *languages;
1083 GSList *l;
1084 guint id;
1085 gint i;
1086
1087 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 1087, ((const char*) (__func__
))
);
1088
1089 /* add the "Plain Text" item before all the others */
1090
1091 /* Translators: "Plain Text" means that no highlight mode is selected in the
1092 * "View->Highlight Mode" submenu and so syntax highlighting is disabled */
1093 action_none = gtk_radio_action_new (LANGUAGE_NONE(const gchar *)"LangNone", _("Plain Text")dcgettext (((void*)0), "Plain Text", 5),
1094 _("Disable syntax highlighting")dcgettext (((void*)0), "Disable syntax highlighting", 5),
1095 NULL((void*)0),
1096 -1);
1097
1098 gtk_action_group_add_action (window->priv->languages_action_group,
1099 GTK_ACTION (action_none)((((GtkAction*) (void *) ((action_none))))));
1100 g_object_unref (action_none);
1101
1102 g_signal_connect (action_none,g_signal_connect_data ((action_none), ("activate"), (((GCallback
) (language_toggled))), (window), ((void*)0), (GConnectFlags)
0)
1103 "activate",g_signal_connect_data ((action_none), ("activate"), (((GCallback
) (language_toggled))), (window), ((void*)0), (GConnectFlags)
0)
1104 G_CALLBACK (language_toggled),g_signal_connect_data ((action_none), ("activate"), (((GCallback
) (language_toggled))), (window), ((void*)0), (GConnectFlags)
0)
1105 window)g_signal_connect_data ((action_none), ("activate"), (((GCallback
) (language_toggled))), (window), ((void*)0), (GConnectFlags)
0)
;
1106
1107 id = gtk_ui_manager_new_merge_id (window->priv->manager);
1108
1109 gtk_ui_manager_add_ui (window->priv->manager,
1110 id,
1111 "/MenuBar/ViewMenu/ViewHighlightModeMenu/LanguagesMenuPlaceholder",
1112 LANGUAGE_NONE(const gchar *)"LangNone",
1113 LANGUAGE_NONE(const gchar *)"LangNone",
1114 GTK_UI_MANAGER_MENUITEM,
1115 TRUE(!(0)));
1116
1117 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action_none)((((GtkToggleAction*) (void *) ((action_none))))), TRUE(!(0)));
1118
1119 /* now add all the known languages */
1120 languages = pluma_language_manager_list_languages_sorted (pluma_get_language_manager (),
1121 FALSE(0));
1122
1123 for (l = languages, i = 0; l != NULL((void*)0); l = l->next, ++i)
1124 {
1125 create_language_menu_item (l->data,
1126 i,
1127 id,
1128 window);
1129 }
1130
1131 g_slist_free (languages);
1132}
1133
1134static void
1135update_languages_menu (PlumaWindow *window)
1136{
1137 PlumaDocument *doc;
1138 GList *actions;
1139 GList *l;
1140 GtkAction *action;
1141 GtkSourceLanguage *lang;
1142 const gchar *lang_id;
1143
1144 doc = pluma_window_get_active_document (window);
1145 if (doc == NULL((void*)0))
1146 return;
1147
1148 lang = pluma_document_get_language (doc);
1149 if (lang != NULL((void*)0))
1150 lang_id = gtk_source_language_get_id (lang);
1151 else
1152 lang_id = LANGUAGE_NONE(const gchar *)"LangNone";
1153
1154 actions = gtk_action_group_list_actions (window->priv->languages_action_group);
1155
1156 /* prevent recursion */
1157 for (l = actions; l != NULL((void*)0); l = l->next)
1158 {
1159 g_signal_handlers_block_by_func (GTK_ACTION (l->data),g_signal_handlers_block_matched ((((((GtkAction*) (void *) ((
l->data)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (language_toggled))), (window
))
1160 G_CALLBACK (language_toggled),g_signal_handlers_block_matched ((((((GtkAction*) (void *) ((
l->data)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (language_toggled))), (window
))
1161 window)g_signal_handlers_block_matched ((((((GtkAction*) (void *) ((
l->data)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (language_toggled))), (window
))
;
1162 }
1163
1164 action = gtk_action_group_get_action (window->priv->languages_action_group,
1165 lang_id);
1166
1167 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action))))), TRUE(!(0)));
1168
1169 for (l = actions; l != NULL((void*)0); l = l->next)
1170 {
1171 g_signal_handlers_unblock_by_func (GTK_ACTION (l->data),g_signal_handlers_unblock_matched ((((((GtkAction*) (void *) (
(l->data)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (language_toggled))), (window
))
1172 G_CALLBACK (language_toggled),g_signal_handlers_unblock_matched ((((((GtkAction*) (void *) (
(l->data)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (language_toggled))), (window
))
1173 window)g_signal_handlers_unblock_matched ((((((GtkAction*) (void *) (
(l->data)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (((GCallback) (language_toggled))), (window
))
;
1174 }
1175
1176 g_list_free (actions);
1177}
1178
1179void
1180_pluma_recent_add (PlumaWindow *window,
1181 const gchar *uri,
1182 const gchar *mime)
1183{
1184 GtkRecentManager *recent_manager;
1185 GtkRecentData recent_data;
1186
1187 static gchar *groups[2] = {
1188 "pluma",
1189 NULL((void*)0)
1190 };
1191
1192 recent_manager = gtk_recent_manager_get_default ();
1193
1194 recent_data.display_name = NULL((void*)0);
1195 recent_data.description = NULL((void*)0);
1196 recent_data.mime_type = (gchar *) mime;
1197 recent_data.app_name = (gchar *) g_get_application_name ();
1198 recent_data.app_exec = g_strjoin (" ", g_get_prgname (), "%u", NULL((void*)0));
1199 recent_data.groups = groups;
1200 recent_data.is_private = FALSE(0);
1201
1202 gtk_recent_manager_add_full (recent_manager,
1203 uri,
1204 &recent_data);
1205
1206 g_free (recent_data.app_exec);
1207}
1208
1209void
1210_pluma_recent_remove (PlumaWindow *window,
1211 const gchar *uri)
1212{
1213 GtkRecentManager *recent_manager;
1214
1215 recent_manager = gtk_recent_manager_get_default ();
1216
1217 gtk_recent_manager_remove_item (recent_manager, uri, NULL((void*)0));
1218}
1219
1220static void
1221open_recent_file (const gchar *uri,
1222 PlumaWindow *window)
1223{
1224 GSList *uris = NULL((void*)0);
1225
1226 uris = g_slist_prepend (uris, (gpointer) uri);
1227
1228 if (pluma_commands_load_uris (window, uris, NULL((void*)0), 0) != 1)
1229 {
1230 _pluma_recent_remove (window, uri);
1231 }
1232
1233 g_slist_free (uris);
1234}
1235
1236static void
1237recent_chooser_item_activated (GtkRecentChooser *chooser,
1238 PlumaWindow *window)
1239{
1240 gchar *uri;
1241
1242 uri = gtk_recent_chooser_get_current_uri (chooser);
1243
1244 open_recent_file (uri, window);
1245
1246 g_free (uri);
1247}
1248
1249static void
1250recents_menu_activate (GtkAction *action,
1251 PlumaWindow *window)
1252{
1253 GtkRecentInfo *info;
1254 const gchar *uri;
1255
1256 info = g_object_get_data (G_OBJECT (action)((((GObject*) (void *) ((action))))), "gtk-recent-info");
1257 g_return_if_fail (info != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_70
; if (info != ((void*)0)) _g_boolean_var_70 = 1; else _g_boolean_var_70
= 0; _g_boolean_var_70; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "info != NULL"); return
; } } while (0)
;
1258
1259 uri = gtk_recent_info_get_uri (info);
1260
1261 open_recent_file (uri, window);
1262}
1263
1264static gint
1265sort_recents_mru (GtkRecentInfo *a, GtkRecentInfo *b)
1266{
1267 return (gtk_recent_info_get_modified (b) - gtk_recent_info_get_modified (a));
1268}
1269
1270static void update_recent_files_menu (PlumaWindow *window);
1271
1272static void
1273recent_manager_changed (GtkRecentManager *manager,
1274 PlumaWindow *window)
1275{
1276 /* regenerate the menu when the model changes */
1277 update_recent_files_menu (window);
1278}
1279
1280/*
1281 * Manually construct the inline recents list in the File menu.
1282 * Hopefully gtk 2.12 will add support for it.
1283 */
1284static void
1285update_recent_files_menu (PlumaWindow *window)
1286{
1287 PlumaWindowPrivate *p = window->priv;
1288 GtkRecentManager *recent_manager;
1289 guint max_recents;
1290 GList *actions, *l, *items;
1291 GList *filtered_items = NULL((void*)0);
1292 gint i;
1293
1294 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 1294, ((const char*) (__func__
))
);
1295
1296 max_recents = g_settings_get_uint (window->priv->editor_settings, PLUMA_SETTINGS_MAX_RECENTS"max-recents");
1297
1298 g_return_if_fail (p->recents_action_group != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_71
; if (p->recents_action_group != ((void*)0)) _g_boolean_var_71
= 1; else _g_boolean_var_71 = 0; _g_boolean_var_71; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "p->recents_action_group != NULL"); return
; } } while (0)
;
1299
1300 if (p->recents_menu_ui_id != 0)
1301 gtk_ui_manager_remove_ui (p->manager, p->recents_menu_ui_id);
1302
1303 actions = gtk_action_group_list_actions (p->recents_action_group);
1304 for (l = actions; l != NULL((void*)0); l = l->next)
1305 {
1306 g_signal_handlers_disconnect_by_func (GTK_ACTION (l->data),g_signal_handlers_disconnect_matched ((((((GtkAction*) (void *
) ((l->data)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC
| G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0), (((GCallback) (recents_menu_activate
))), (window))
1307 G_CALLBACK (recents_menu_activate),g_signal_handlers_disconnect_matched ((((((GtkAction*) (void *
) ((l->data)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC
| G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0), (((GCallback) (recents_menu_activate
))), (window))
1308 window)g_signal_handlers_disconnect_matched ((((((GtkAction*) (void *
) ((l->data)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC
| G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0), (((GCallback) (recents_menu_activate
))), (window))
;
1309 gtk_action_group_remove_action (p->recents_action_group,
1310 GTK_ACTION (l->data)((((GtkAction*) (void *) ((l->data))))));
1311 }
1312 g_list_free (actions);
1313
1314 p->recents_menu_ui_id = gtk_ui_manager_new_merge_id (p->manager);
1315
1316 recent_manager = gtk_recent_manager_get_default ();
1317 items = gtk_recent_manager_get_items (recent_manager);
1318
1319 /* filter */
1320 for (l = items; l != NULL((void*)0); l = l->next)
1321 {
1322 GtkRecentInfo *info = l->data;
1323
1324 if (!gtk_recent_info_has_group (info, "pluma"))
1325 continue;
1326
1327 filtered_items = g_list_prepend (filtered_items, info);
1328 }
1329
1330 /* sort */
1331 filtered_items = g_list_sort (filtered_items,
1332 (GCompareFunc) sort_recents_mru);
1333
1334 i = 0;
1335 for (l = filtered_items; l != NULL((void*)0); l = l->next)
1336 {
1337 gchar *action_name;
1338 const gchar *display_name;
1339 gchar *escaped;
1340 gchar *label;
1341 gchar *uri;
1342 gchar *ruri;
1343 gchar *tip;
1344 GtkAction *action;
1345 GtkRecentInfo *info = l->data;
1346
1347 /* clamp */
1348 if (i >= max_recents)
1349 break;
1350
1351 i++;
1352
1353 action_name = g_strdup_printf ("recent-info-%d", i);
1354
1355 display_name = gtk_recent_info_get_display_name (info);
1356 escaped = pluma_utils_escape_underscores (display_name, -1);
1357 if (i >= 10)
1358 label = g_strdup_printf ("%d. %s",
1359 i,
1360 escaped);
1361 else
1362 label = g_strdup_printf ("_%d. %s",
1363 i,
1364 escaped);
1365 g_free (escaped);
1366
1367 /* gtk_recent_info_get_uri_display (info) is buggy and
1368 * works only for local files */
1369 uri = pluma_utils_uri_for_display (gtk_recent_info_get_uri (info));
1370 ruri = pluma_utils_replace_home_dir_with_tilde (uri);
1371 g_free (uri);
1372
1373 /* Translators: %s is a URI */
1374 tip = g_strdup_printf (_("Open '%s'")dcgettext (((void*)0), "Open '%s'", 5), ruri);
1375 g_free (ruri);
1376
1377 action = gtk_action_new (action_name,
1378 label,
1379 tip,
1380 NULL((void*)0));
1381
1382 g_object_set_data_full (G_OBJECT (action)((((GObject*) (void *) ((action))))),
1383 "gtk-recent-info",
1384 gtk_recent_info_ref (info),
1385 (GDestroyNotify) gtk_recent_info_unref);
1386
1387 g_signal_connect (action,g_signal_connect_data ((action), ("activate"), (((GCallback) (
recents_menu_activate))), (window), ((void*)0), (GConnectFlags
) 0)
1388 "activate",g_signal_connect_data ((action), ("activate"), (((GCallback) (
recents_menu_activate))), (window), ((void*)0), (GConnectFlags
) 0)
1389 G_CALLBACK (recents_menu_activate),g_signal_connect_data ((action), ("activate"), (((GCallback) (
recents_menu_activate))), (window), ((void*)0), (GConnectFlags
) 0)
1390 window)g_signal_connect_data ((action), ("activate"), (((GCallback) (
recents_menu_activate))), (window), ((void*)0), (GConnectFlags
) 0)
;
1391
1392 gtk_action_group_add_action (p->recents_action_group,
1393 action);
1394 g_object_unref (action);
1395
1396 gtk_ui_manager_add_ui (p->manager,
1397 p->recents_menu_ui_id,
1398 "/MenuBar/FileMenu/FileRecentsPlaceholder",
1399 action_name,
1400 action_name,
1401 GTK_UI_MANAGER_MENUITEM,
1402 FALSE(0));
1403
1404 g_free (action_name);
1405 g_free (label);
1406 g_free (tip);
1407 }
1408
1409 g_list_free (filtered_items);
1410
1411 g_list_free_full (items, (GDestroyNotify) gtk_recent_info_unref);
1412}
1413
1414static void
1415set_non_homogeneus (GtkWidget *widget, gpointer data)
1416{
1417 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget)((((GtkToolItem*) (void *) ((widget))))), FALSE(0));
1418}
1419
1420static void
1421toolbar_visibility_changed (GtkWidget *toolbar,
1422 PlumaWindow *window)
1423{
1424 gboolean visible;
1425 GtkAction *action;
1426
1427 visible = gtk_widget_get_visible (toolbar);
1428
1429 g_settings_set_boolean (window->priv->editor_settings,
1430 PLUMA_SETTINGS_TOOLBAR_VISIBLE"toolbar-visible", visible);
1431
1432 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group,
1433 "ViewToolbar");
1434
1435 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action)))))) != visible)
1436 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action))))), visible);
1437}
1438
1439static GtkWidget *
1440setup_toolbar_open_button (PlumaWindow *window,
1441 GtkWidget *toolbar)
1442{
1443 GtkRecentManager *recent_manager;
1444 GtkRecentFilter *filter;
1445 GtkWidget *toolbar_recent_menu;
1446 GtkToolItem *open_button;
1447 GtkAction *action;
1448 guint max_recents;
1449
1450 recent_manager = gtk_recent_manager_get_default ();
1451
1452 max_recents = g_settings_get_uint (window->priv->editor_settings, PLUMA_SETTINGS_MAX_RECENTS"max-recents");
1453
1454 /* recent files menu tool button */
1455 toolbar_recent_menu = gtk_recent_chooser_menu_new_for_manager (recent_manager);
1456
1457 gtk_recent_chooser_set_local_only (GTK_RECENT_CHOOSER (toolbar_recent_menu)((((GtkRecentChooser*) (void *) ((toolbar_recent_menu))))),
1458 FALSE(0));
1459 gtk_recent_chooser_set_sort_type (GTK_RECENT_CHOOSER (toolbar_recent_menu)((((GtkRecentChooser*) (void *) ((toolbar_recent_menu))))),
1460 GTK_RECENT_SORT_MRU);
1461 gtk_recent_chooser_set_limit (GTK_RECENT_CHOOSER (toolbar_recent_menu)((((GtkRecentChooser*) (void *) ((toolbar_recent_menu))))),
1462 max_recents);
1463
1464 filter = gtk_recent_filter_new ();
1465 gtk_recent_filter_add_group (filter, "pluma");
1466 gtk_recent_chooser_set_filter (GTK_RECENT_CHOOSER (toolbar_recent_menu)((((GtkRecentChooser*) (void *) ((toolbar_recent_menu))))),
1467 filter);
1468
1469 g_signal_connect (toolbar_recent_menu,g_signal_connect_data ((toolbar_recent_menu), ("item_activated"
), (((GCallback) (recent_chooser_item_activated))), (window),
((void*)0), (GConnectFlags) 0)
1470 "item_activated",g_signal_connect_data ((toolbar_recent_menu), ("item_activated"
), (((GCallback) (recent_chooser_item_activated))), (window),
((void*)0), (GConnectFlags) 0)
1471 G_CALLBACK (recent_chooser_item_activated),g_signal_connect_data ((toolbar_recent_menu), ("item_activated"
), (((GCallback) (recent_chooser_item_activated))), (window),
((void*)0), (GConnectFlags) 0)
1472 window)g_signal_connect_data ((toolbar_recent_menu), ("item_activated"
), (((GCallback) (recent_chooser_item_activated))), (window),
((void*)0), (GConnectFlags) 0)
;
1473
1474 /* add the custom Open button to the toolbar */
1475 open_button = gtk_menu_tool_button_new (gtk_image_new_from_icon_name ("document-open",
1476 GTK_ICON_SIZE_MENU),
1477 _("Open a file")dcgettext (((void*)0), "Open a file", 5));
1478
1479 gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (open_button)((((GtkMenuToolButton*) (void *) ((open_button))))),
1480 toolbar_recent_menu);
1481
1482 gtk_menu_tool_button_set_arrow_tooltip_text (GTK_MENU_TOOL_BUTTON (open_button)((((GtkMenuToolButton*) (void *) ((open_button))))),
1483 _("Open a recently used file")dcgettext (((void*)0), "Open a recently used file", 5));
1484
1485 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group,
1486 "FileOpen");
1487 g_object_set (action,
1488 "is_important", TRUE(!(0)),
1489 "short_label", _("Open")dcgettext (((void*)0), "Open", 5),
1490 NULL((void*)0));
1491 gtk_activatable_set_related_action (GTK_ACTIVATABLE (open_button)((((GtkActivatable*) (void *) ((open_button))))),
1492 action);
1493
1494 gtk_toolbar_insert (GTK_TOOLBAR (toolbar)((((GtkToolbar*) (void *) ((toolbar))))),
1495 open_button,
1496 1);
1497
1498 return toolbar_recent_menu;
1499}
1500
1501static void
1502create_menu_bar_and_toolbar (PlumaWindow *window,
1503 GtkWidget *main_box)
1504{
1505 GtkActionGroup *action_group;
1506 GtkAction *action;
1507 GtkUIManager *manager;
1508 GtkRecentManager *recent_manager;
1509 GError *error = NULL((void*)0);
1510
1511 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 1511, ((const char*) (__func__
))
);
1512
1513 manager = gtk_ui_manager_new ();
1514 window->priv->manager = manager;
1515
1516 gtk_window_add_accel_group (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))),
1517 gtk_ui_manager_get_accel_group (manager));
1518
1519 action_group = gtk_action_group_new ("PlumaWindowAlwaysSensitiveActions");
1520 gtk_action_group_set_translation_domain (action_group, NULL((void*)0));
1521 gtk_action_group_add_actions (action_group,
1522 pluma_always_sensitive_menu_entries,
1523 G_N_ELEMENTS (pluma_always_sensitive_menu_entries)(sizeof (pluma_always_sensitive_menu_entries) / sizeof ((pluma_always_sensitive_menu_entries
)[0]))
,
1524 window);
1525 gtk_action_group_add_toggle_actions (action_group,
1526 pluma_always_sensitive_toggle_menu_entries,
1527 G_N_ELEMENTS (pluma_always_sensitive_toggle_menu_entries)(sizeof (pluma_always_sensitive_toggle_menu_entries) / sizeof
((pluma_always_sensitive_toggle_menu_entries)[0]))
,
1528 window);
1529
1530 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1531 g_object_unref (action_group);
1532 window->priv->always_sensitive_action_group = action_group;
1533
1534 action_group = gtk_action_group_new ("PlumaWindowActions");
1535 gtk_action_group_set_translation_domain (action_group, NULL((void*)0));
1536 gtk_action_group_add_actions (action_group,
1537 pluma_menu_entries,
1538 G_N_ELEMENTS (pluma_menu_entries)(sizeof (pluma_menu_entries) / sizeof ((pluma_menu_entries)[0
]))
,
1539 window);
1540 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1541 g_object_unref (action_group);
1542 window->priv->action_group = action_group;
1543
1544 /* set short labels to use in the toolbar */
1545 action = gtk_action_group_get_action (action_group, "FileSave");
1546 g_object_set (action, "short_label", _("Save")dcgettext (((void*)0), "Save", 5), NULL((void*)0));
1547 action = gtk_action_group_get_action (action_group, "FilePrint");
1548 g_object_set (action, "short_label", _("Print")dcgettext (((void*)0), "Print", 5), NULL((void*)0));
1549 action = gtk_action_group_get_action (action_group, "SearchFind");
1550 g_object_set (action, "short_label", _("Find")dcgettext (((void*)0), "Find", 5), NULL((void*)0));
1551 action = gtk_action_group_get_action (action_group, "SearchReplace");
1552 g_object_set (action, "short_label", _("Replace")dcgettext (((void*)0), "Replace", 5), NULL((void*)0));
1553
1554 /* set which actions should have priority on the toolbar */
1555 action = gtk_action_group_get_action (action_group, "FileSave");
1556 g_object_set (action, "is_important", TRUE(!(0)), NULL((void*)0));
1557 action = gtk_action_group_get_action (action_group, "EditUndo");
1558 g_object_set (action, "is_important", TRUE(!(0)), NULL((void*)0));
1559
1560 action_group = gtk_action_group_new ("PlumaQuitWindowActions");
1561 gtk_action_group_set_translation_domain (action_group, NULL((void*)0));
1562 gtk_action_group_add_actions (action_group,
1563 pluma_quit_menu_entries,
1564 G_N_ELEMENTS (pluma_quit_menu_entries)(sizeof (pluma_quit_menu_entries) / sizeof ((pluma_quit_menu_entries
)[0]))
,
1565 window);
1566
1567 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1568 g_object_unref (action_group);
1569 window->priv->quit_action_group = action_group;
1570
1571 action_group = gtk_action_group_new ("PlumaCloseWindowActions");
1572 gtk_action_group_set_translation_domain (action_group, NULL((void*)0));
1573 gtk_action_group_add_actions (action_group,
1574 pluma_close_menu_entries,
1575 G_N_ELEMENTS (pluma_close_menu_entries)(sizeof (pluma_close_menu_entries) / sizeof ((pluma_close_menu_entries
)[0]))
,
1576 window);
1577
1578 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1579 g_object_unref (action_group);
1580 window->priv->close_action_group = action_group;
1581
1582 action_group = gtk_action_group_new ("PlumaWindowPanesActions");
1583 gtk_action_group_set_translation_domain (action_group, NULL((void*)0));
1584 gtk_action_group_add_toggle_actions (action_group,
1585 pluma_panes_toggle_menu_entries,
1586 G_N_ELEMENTS (pluma_panes_toggle_menu_entries)(sizeof (pluma_panes_toggle_menu_entries) / sizeof ((pluma_panes_toggle_menu_entries
)[0]))
,
1587 window);
1588
1589 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1590 g_object_unref (action_group);
1591 window->priv->panes_action_group = action_group;
1592
1593 /* now load the UI definition */
1594 gtk_ui_manager_add_ui_from_file (manager,
1595 PLUMA_DATADIR"/usr/local/share/pluma" "/ui/pluma-ui.xml",
1596 &error);
1597 if (error != NULL((void*)0))
1598 {
1599 g_warning ("Could not merge %s: %s",
1600 PLUMA_DATADIR"/usr/local/share/pluma" "/ui/pluma-ui.xml",
1601 error->message);
1602 g_error_free (error);
1603 }
1604
1605 /* show tooltips in the statusbar */
1606 g_signal_connect (manager,g_signal_connect_data ((manager), ("connect_proxy"), (((GCallback
) (connect_proxy_cb))), (window), ((void*)0), (GConnectFlags)
0)
1607 "connect_proxy",g_signal_connect_data ((manager), ("connect_proxy"), (((GCallback
) (connect_proxy_cb))), (window), ((void*)0), (GConnectFlags)
0)
1608 G_CALLBACK (connect_proxy_cb),g_signal_connect_data ((manager), ("connect_proxy"), (((GCallback
) (connect_proxy_cb))), (window), ((void*)0), (GConnectFlags)
0)
1609 window)g_signal_connect_data ((manager), ("connect_proxy"), (((GCallback
) (connect_proxy_cb))), (window), ((void*)0), (GConnectFlags)
0)
;
1610 g_signal_connect (manager,g_signal_connect_data ((manager), ("disconnect_proxy"), (((GCallback
) (disconnect_proxy_cb))), (window), ((void*)0), (GConnectFlags
) 0)
1611 "disconnect_proxy",g_signal_connect_data ((manager), ("disconnect_proxy"), (((GCallback
) (disconnect_proxy_cb))), (window), ((void*)0), (GConnectFlags
) 0)
1612 G_CALLBACK (disconnect_proxy_cb),g_signal_connect_data ((manager), ("disconnect_proxy"), (((GCallback
) (disconnect_proxy_cb))), (window), ((void*)0), (GConnectFlags
) 0)
1613 window)g_signal_connect_data ((manager), ("disconnect_proxy"), (((GCallback
) (disconnect_proxy_cb))), (window), ((void*)0), (GConnectFlags
) 0)
;
1614
1615 /* recent files menu */
1616 action_group = gtk_action_group_new ("RecentFilesActions");
1617 gtk_action_group_set_translation_domain (action_group, NULL((void*)0));
1618 window->priv->recents_action_group = action_group;
1619 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1620 g_object_unref (action_group);
1621
1622 recent_manager = gtk_recent_manager_get_default ();
1623 window->priv->recents_handler_id = g_signal_connect (recent_manager,g_signal_connect_data ((recent_manager), ("changed"), (((GCallback
) (recent_manager_changed))), (window), ((void*)0), (GConnectFlags
) 0)
1624 "changed",g_signal_connect_data ((recent_manager), ("changed"), (((GCallback
) (recent_manager_changed))), (window), ((void*)0), (GConnectFlags
) 0)
1625 G_CALLBACK (recent_manager_changed),g_signal_connect_data ((recent_manager), ("changed"), (((GCallback
) (recent_manager_changed))), (window), ((void*)0), (GConnectFlags
) 0)
1626 window)g_signal_connect_data ((recent_manager), ("changed"), (((GCallback
) (recent_manager_changed))), (window), ((void*)0), (GConnectFlags
) 0)
;
1627 update_recent_files_menu (window);
1628
1629 /* languages menu */
1630 action_group = gtk_action_group_new ("LanguagesActions");
1631 gtk_action_group_set_translation_domain (action_group, NULL((void*)0));
1632 window->priv->languages_action_group = action_group;
1633 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1634 g_object_unref (action_group);
1635 create_languages_menu (window);
1636
1637 /* list of open documents menu */
1638 action_group = gtk_action_group_new ("DocumentsListActions");
1639 gtk_action_group_set_translation_domain (action_group, NULL((void*)0));
1640 window->priv->documents_list_action_group = action_group;
1641 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1642 g_object_unref (action_group);
1643
1644 window->priv->menubar = gtk_ui_manager_get_widget (manager, "/MenuBar");
1645 gtk_box_pack_start (GTK_BOX (main_box)((((GtkBox*) (void *) ((main_box))))),
1646 window->priv->menubar,
1647 FALSE(0),
1648 FALSE(0),
1649 0);
1650
1651 window->priv->toolbar = gtk_ui_manager_get_widget (manager, "/ToolBar");
1652 gtk_style_context_add_class (gtk_widget_get_style_context (window->priv->toolbar),
1653 GTK_STYLE_CLASS_PRIMARY_TOOLBAR"primary-toolbar");
1654 gtk_box_pack_start (GTK_BOX (main_box)((((GtkBox*) (void *) ((main_box))))),
1655 window->priv->toolbar,
1656 FALSE(0),
1657 FALSE(0),
1658 0);
1659
1660 set_toolbar_style (window, NULL((void*)0));
1661
1662 window->priv->toolbar_recent_menu = setup_toolbar_open_button (window, window->priv->toolbar);
1663
1664 gtk_container_foreach (GTK_CONTAINER (window->priv->toolbar)((((GtkContainer*) (void *) ((window->priv->toolbar))))
)
,
1665 (GtkCallback)set_non_homogeneus,
1666 NULL((void*)0));
1667
1668 g_signal_connect_after (window->priv->toolbar, "show",g_signal_connect_data ((window->priv->toolbar), ("show"
), (((GCallback) (toolbar_visibility_changed))), (window), ((
void*)0), G_CONNECT_AFTER)
1669 G_CALLBACK (toolbar_visibility_changed),g_signal_connect_data ((window->priv->toolbar), ("show"
), (((GCallback) (toolbar_visibility_changed))), (window), ((
void*)0), G_CONNECT_AFTER)
1670 window)g_signal_connect_data ((window->priv->toolbar), ("show"
), (((GCallback) (toolbar_visibility_changed))), (window), ((
void*)0), G_CONNECT_AFTER)
;
1671 g_signal_connect_after (window->priv->toolbar, "hide",g_signal_connect_data ((window->priv->toolbar), ("hide"
), (((GCallback) (toolbar_visibility_changed))), (window), ((
void*)0), G_CONNECT_AFTER)
1672 G_CALLBACK (toolbar_visibility_changed),g_signal_connect_data ((window->priv->toolbar), ("hide"
), (((GCallback) (toolbar_visibility_changed))), (window), ((
void*)0), G_CONNECT_AFTER)
1673 window)g_signal_connect_data ((window->priv->toolbar), ("hide"
), (((GCallback) (toolbar_visibility_changed))), (window), ((
void*)0), G_CONNECT_AFTER)
;
1674}
1675
1676static void
1677documents_list_menu_activate (GtkToggleAction *action,
1678 PlumaWindow *window)
1679{
1680 gint n;
1681
1682 if (gtk_toggle_action_get_active (action) == FALSE(0))
1683 return;
1684
1685 n = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)((((GtkRadioAction*) (void *) ((action))))));
1686 gtk_notebook_set_current_page (GTK_NOTEBOOK (window->priv->notebook)((((GtkNotebook*) (void *) ((window->priv->notebook))))
)
, n);
1687}
1688
1689static gchar *
1690get_menu_tip_for_tab (PlumaTab *tab)
1691{
1692 PlumaDocument *doc;
1693 gchar *uri;
1694 gchar *ruri;
1695 gchar *tip;
1696
1697 doc = pluma_tab_get_document (tab);
1698
1699 uri = pluma_document_get_uri_for_display (doc);
1700 ruri = pluma_utils_replace_home_dir_with_tilde (uri);
1701 g_free (uri);
1702
1703 /* Translators: %s is a URI */
1704 tip = g_strdup_printf (_("Activate '%s'")dcgettext (((void*)0), "Activate '%s'", 5), ruri);
1705 g_free (ruri);
1706
1707 return tip;
1708}
1709
1710static void
1711update_documents_list_menu (PlumaWindow *window)
1712{
1713 PlumaWindowPrivate *p = window->priv;
1714 GList *actions, *l;
1715 gint n, i;
1716 guint id;
1717 GSList *group = NULL((void*)0);
1718
1719 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 1719, ((const char*) (__func__
))
);
1720
1721 g_return_if_fail (p->documents_list_action_group != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_72
; if (p->documents_list_action_group != ((void*)0)) _g_boolean_var_72
= 1; else _g_boolean_var_72 = 0; _g_boolean_var_72; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "p->documents_list_action_group != NULL");
return; } } while (0)
;
1722
1723 if (p->documents_list_menu_ui_id != 0)
1724 gtk_ui_manager_remove_ui (p->manager,
1725 p->documents_list_menu_ui_id);
1726
1727 actions = gtk_action_group_list_actions (p->documents_list_action_group);
1728 for (l = actions; l != NULL((void*)0); l = l->next)
1729 {
1730 g_signal_handlers_disconnect_by_func (GTK_ACTION (l->data),g_signal_handlers_disconnect_matched ((((((GtkAction*) (void *
) ((l->data)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC
| G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0), (((GCallback) (documents_list_menu_activate
))), (window))
1731 G_CALLBACK (documents_list_menu_activate),g_signal_handlers_disconnect_matched ((((((GtkAction*) (void *
) ((l->data)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC
| G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0), (((GCallback) (documents_list_menu_activate
))), (window))
1732 window)g_signal_handlers_disconnect_matched ((((((GtkAction*) (void *
) ((l->data)))))), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC
| G_SIGNAL_MATCH_DATA), 0, 0, ((void*)0), (((GCallback) (documents_list_menu_activate
))), (window))
;
1733 gtk_action_group_remove_action (p->documents_list_action_group,
1734 GTK_ACTION (l->data)((((GtkAction*) (void *) ((l->data))))));
1735 }
1736 g_list_free (actions);
1737
1738 n = gtk_notebook_get_n_pages (GTK_NOTEBOOK (p->notebook)((((GtkNotebook*) (void *) ((p->notebook))))));
1739
1740 id = (n > 0) ? gtk_ui_manager_new_merge_id (p->manager) : 0;
1741
1742 for (i = 0; i < n; i++)
1743 {
1744 GtkWidget *tab;
1745 GtkRadioAction *action;
1746 gchar *action_name;
1747 gchar *tab_name;
1748 gchar *name;
1749 gchar *tip;
1750 gchar *accel;
1751
1752 tab = gtk_notebook_get_nth_page (GTK_NOTEBOOK (p->notebook)((((GtkNotebook*) (void *) ((p->notebook))))), i);
1753
1754 /* NOTE: the action is associated to the position of the tab in
1755 * the notebook not to the tab itself! This is needed to work
1756 * around the gtk+ bug #170727: gtk leaves around the accels
1757 * of the action. Since the accel depends on the tab position
1758 * the problem is worked around, action with the same name always
1759 * get the same accel.
1760 */
1761 action_name = g_strdup_printf ("Tab_%d", i);
1762 tab_name = _pluma_tab_get_name (PLUMA_TAB (tab)((((PlumaTab*) (void *) ((tab))))));
1763 name = pluma_utils_escape_underscores (tab_name, -1);
1764 tip = get_menu_tip_for_tab (PLUMA_TAB (tab)((((PlumaTab*) (void *) ((tab))))));
1765
1766 /* alt + 1, 2, 3... 0 to switch to the first ten tabs */
1767 accel = (i < 10) ? g_strdup_printf ("<alt>%d", (i + 1) % 10) : NULL((void*)0);
1768
1769 action = gtk_radio_action_new (action_name,
1770 name,
1771 tip,
1772 NULL((void*)0),
1773 i);
1774
1775 if (group != NULL((void*)0))
1776 gtk_radio_action_set_group (action, group);
1777
1778 /* note that group changes each time we add an action, so it must be updated */
1779 group = gtk_radio_action_get_group (action);
1780
1781 gtk_action_group_add_action_with_accel (p->documents_list_action_group,
1782 GTK_ACTION (action)((((GtkAction*) (void *) ((action))))),
1783 accel);
1784
1785 g_signal_connect (action,g_signal_connect_data ((action), ("activate"), (((GCallback) (
documents_list_menu_activate))), (window), ((void*)0), (GConnectFlags
) 0)
1786 "activate",g_signal_connect_data ((action), ("activate"), (((GCallback) (
documents_list_menu_activate))), (window), ((void*)0), (GConnectFlags
) 0)
1787 G_CALLBACK (documents_list_menu_activate),g_signal_connect_data ((action), ("activate"), (((GCallback) (
documents_list_menu_activate))), (window), ((void*)0), (GConnectFlags
) 0)
1788 window)g_signal_connect_data ((action), ("activate"), (((GCallback) (
documents_list_menu_activate))), (window), ((void*)0), (GConnectFlags
) 0)
;
1789
1790 gtk_ui_manager_add_ui (p->manager,
1791 id,
1792 "/MenuBar/DocumentsMenu/DocumentsListPlaceholder",
1793 action_name, action_name,
1794 GTK_UI_MANAGER_MENUITEM,
1795 FALSE(0));
1796
1797 if (PLUMA_TAB (tab)((((PlumaTab*) (void *) ((tab))))) == p->active_tab)
1798 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action))))), TRUE(!(0)));
1799
1800 g_object_unref (action);
1801
1802 g_free (action_name);
1803 g_free (tab_name);
1804 g_free (name);
1805 g_free (tip);
1806 g_free (accel);
1807 }
1808
1809 p->documents_list_menu_ui_id = id;
1810}
1811
1812/* Returns TRUE if status bar is visible */
1813static gboolean
1814set_statusbar_style (PlumaWindow *window,
1815 PlumaWindow *origin)
1816{
1817 GtkAction *action;
1818 gboolean visible;
1819
1820 if (origin == NULL((void*)0))
1821 visible = g_settings_get_boolean (window->priv->editor_settings,
1822 PLUMA_SETTINGS_STATUSBAR_VISIBLE"statusbar-visible");
1823 else
1824 visible = gtk_widget_get_visible (origin->priv->statusbar);
1825
1826 if (visible)
1827 gtk_widget_show (window->priv->statusbar);
1828 else
1829 gtk_widget_hide (window->priv->statusbar);
1830
1831 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group,
1832 "ViewStatusbar");
1833
1834 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action)))))) != visible)
1835 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action))))), visible);
1836
1837 return visible;
1838}
1839
1840static void
1841statusbar_visibility_changed (GtkWidget *statusbar,
1842 PlumaWindow *window)
1843{
1844 gboolean visible;
1845 GtkAction *action;
1846
1847 visible = gtk_widget_get_visible (statusbar);
1848
1849 g_settings_set_boolean (window->priv->editor_settings,
1850 PLUMA_SETTINGS_STATUSBAR_VISIBLE"statusbar-visible", visible);
1851
1852 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group,
1853 "ViewStatusbar");
1854
1855 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action)))))) != visible)
1856 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action))))), visible);
1857}
1858
1859static void
1860tab_width_combo_changed (PlumaStatusComboBox *combo,
1861 GtkMenuItem *item,
1862 PlumaWindow *window)
1863{
1864 PlumaView *view;
1865 guint width_data = 0;
1866
1867 view = pluma_window_get_active_view (window);
1868
1869 if (!view)
1870 return;
1871
1872 width_data = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item), TAB_WIDTH_DATA))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
item))))), "PlumaWindowTabWidthData")))
;
1873
1874 if (width_data == 0)
1875 return;
1876
1877 g_signal_handler_block (view, window->priv->tab_width_id);
1878 gtk_source_view_set_tab_width (GTK_SOURCE_VIEW (view)((((GtkSourceView*) (void *) ((view))))), width_data);
1879 g_signal_handler_unblock (view, window->priv->tab_width_id);
1880}
1881
1882static void
1883use_spaces_toggled (GtkCheckMenuItem *item,
1884 PlumaWindow *window)
1885{
1886 PlumaView *view;
1887
1888 view = pluma_window_get_active_view (window);
1889
1890 g_signal_handler_block (view, window->priv->spaces_instead_of_tabs_id);
1891 gtk_source_view_set_insert_spaces_instead_of_tabs (GTK_SOURCE_VIEW (view)((((GtkSourceView*) (void *) ((view))))),
1892 gtk_check_menu_item_get_active (item));
1893 g_signal_handler_unblock (view, window->priv->spaces_instead_of_tabs_id);
1894}
1895
1896static void
1897language_combo_changed (PlumaStatusComboBox *combo,
1898 GtkMenuItem *item,
1899 PlumaWindow *window)
1900{
1901 PlumaDocument *doc;
1902 GtkSourceLanguage *language;
1903
1904 doc = pluma_window_get_active_document (window);
1905
1906 if (!doc)
1907 return;
1908
1909 language = GTK_SOURCE_LANGUAGE (g_object_get_data (G_OBJECT (item), LANGUAGE_DATA))((((GtkSourceLanguage*) (void *) ((g_object_get_data (((((GObject
*) (void *) ((item))))), "PlumaWindowLanguageData"))))))
;
1910
1911 g_signal_handler_block (doc, window->priv->language_changed_id);
1912 pluma_document_set_language (doc, language);
1913 g_signal_handler_unblock (doc, window->priv->language_changed_id);
1914}
1915
1916typedef struct
1917{
1918 const gchar *label;
1919 guint width;
1920} TabWidthDefinition;
1921
1922static void
1923fill_tab_width_combo (PlumaWindow *window)
1924{
1925 static TabWidthDefinition defs[] = {
1926 {"2", 2},
1927 {"4", 4},
1928 {"8", 8},
1929 {"", 0}, /* custom size */
1930 {NULL((void*)0), 0}
1931 };
1932
1933 PlumaStatusComboBox *combo = PLUMA_STATUS_COMBO_BOX (window->priv->tab_width_combo)((((PlumaStatusComboBox*) (void *) ((window->priv->tab_width_combo
)))))
;
1934 guint i = 0;
1935 GtkWidget *item;
1936
1937 while (defs[i].label != NULL((void*)0))
1938 {
1939 item = gtk_menu_item_new_with_label (defs[i].label);
1940 g_object_set_data (G_OBJECT (item)((((GObject*) (void *) ((item))))), TAB_WIDTH_DATA"PlumaWindowTabWidthData", GINT_TO_POINTER (defs[i].width)((gpointer) (glong) (defs[i].width)));
1941
1942 pluma_status_combo_box_add_item (combo,
1943 GTK_MENU_ITEM (item)((((GtkMenuItem*) (void *) ((item))))),
1944 defs[i].label);
1945
1946 if (defs[i].width != 0)
1947 gtk_widget_show (item);
1948
1949 ++i;
1950 }
1951
1952 item = gtk_separator_menu_item_new ();
1953 pluma_status_combo_box_add_item (combo, GTK_MENU_ITEM (item)((((GtkMenuItem*) (void *) ((item))))), NULL((void*)0));
1954 gtk_widget_show (item);
1955
1956 item = gtk_check_menu_item_new_with_label (_("Use Spaces")dcgettext (((void*)0), "Use Spaces", 5));
1957 pluma_status_combo_box_add_item (combo, GTK_MENU_ITEM (item)((((GtkMenuItem*) (void *) ((item))))), NULL((void*)0));
1958 gtk_widget_show (item);
1959
1960 g_signal_connect (item,g_signal_connect_data ((item), ("toggled"), (((GCallback) (use_spaces_toggled
))), (window), ((void*)0), (GConnectFlags) 0)
1961 "toggled",g_signal_connect_data ((item), ("toggled"), (((GCallback) (use_spaces_toggled
))), (window), ((void*)0), (GConnectFlags) 0)
1962 G_CALLBACK (use_spaces_toggled),g_signal_connect_data ((item), ("toggled"), (((GCallback) (use_spaces_toggled
))), (window), ((void*)0), (GConnectFlags) 0)
1963 window)g_signal_connect_data ((item), ("toggled"), (((GCallback) (use_spaces_toggled
))), (window), ((void*)0), (GConnectFlags) 0)
;
1964}
1965
1966static void
1967fill_language_combo (PlumaWindow *window)
1968{
1969 GtkSourceLanguageManager *manager;
1970 GSList *languages;
1971 GSList *item;
1972 GtkWidget *menu_item;
1973 const gchar *name;
1974
1975 manager = pluma_get_language_manager ();
1976 languages = pluma_language_manager_list_languages_sorted (manager, FALSE(0));
1977
1978 name = _("Plain Text")dcgettext (((void*)0), "Plain Text", 5);
1979 menu_item = gtk_menu_item_new_with_label (name);
1980 gtk_widget_show (menu_item);
1981
1982 g_object_set_data (G_OBJECT (menu_item)((((GObject*) (void *) ((menu_item))))), LANGUAGE_DATA"PlumaWindowLanguageData", NULL((void*)0));
1983 pluma_status_combo_box_add_item (PLUMA_STATUS_COMBO_BOX (window->priv->language_combo)((((PlumaStatusComboBox*) (void *) ((window->priv->language_combo
)))))
,
1984 GTK_MENU_ITEM (menu_item)((((GtkMenuItem*) (void *) ((menu_item))))),
1985 name);
1986
1987 for (item = languages; item; item = item->next)
1988 {
1989 GtkSourceLanguage *lang = GTK_SOURCE_LANGUAGE (item->data)((((GtkSourceLanguage*) (void *) ((item->data)))));
1990
1991 name = gtk_source_language_get_name (lang);
1992 menu_item = gtk_menu_item_new_with_label (name);
1993 gtk_widget_show (menu_item);
1994
1995 g_object_set_data_full (G_OBJECT (menu_item)((((GObject*) (void *) ((menu_item))))),
1996 LANGUAGE_DATA"PlumaWindowLanguageData",
1997 g_object_ref (lang)((__typeof__ (lang)) (g_object_ref) (lang)),
1998 (GDestroyNotify)g_object_unref);
1999
2000 pluma_status_combo_box_add_item (PLUMA_STATUS_COMBO_BOX (window->priv->language_combo)((((PlumaStatusComboBox*) (void *) ((window->priv->language_combo
)))))
,
2001 GTK_MENU_ITEM (menu_item)((((GtkMenuItem*) (void *) ((menu_item))))),
2002 name);
2003 }
2004
2005 g_slist_free (languages);
2006}
2007
2008static void
2009create_statusbar (PlumaWindow *window,
2010 GtkWidget *main_box)
2011{
2012 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 2012, ((const char*) (__func__
))
);
2013
2014 window->priv->statusbar = pluma_statusbar_new ();
2015
2016 window->priv->generic_message_cid = gtk_statusbar_get_context_id
2017 (GTK_STATUSBAR (window->priv->statusbar)((((GtkStatusbar*) (void *) ((window->priv->statusbar))
)))
, "generic_message");
2018 window->priv->tip_message_cid = gtk_statusbar_get_context_id
2019 (GTK_STATUSBAR (window->priv->statusbar)((((GtkStatusbar*) (void *) ((window->priv->statusbar))
)))
, "tip_message");
2020
2021 gtk_box_pack_end (GTK_BOX (main_box)((((GtkBox*) (void *) ((main_box))))),
2022 window->priv->statusbar,
2023 FALSE(0),
2024 TRUE(!(0)),
2025 0);
2026
2027 window->priv->tab_width_combo = pluma_status_combo_box_new (_("Tab Width")dcgettext (((void*)0), "Tab Width", 5));
2028 gtk_widget_show (window->priv->tab_width_combo);
2029 gtk_box_pack_end (GTK_BOX (window->priv->statusbar)((((GtkBox*) (void *) ((window->priv->statusbar))))),
2030 window->priv->tab_width_combo,
2031 FALSE(0),
2032 TRUE(!(0)),
2033 0);
2034
2035 fill_tab_width_combo (window);
2036
2037 g_signal_connect (window->priv->tab_width_combo, "changed",g_signal_connect_data ((window->priv->tab_width_combo),
("changed"), (((GCallback) (tab_width_combo_changed))), (window
), ((void*)0), (GConnectFlags) 0)
2038 G_CALLBACK (tab_width_combo_changed),g_signal_connect_data ((window->priv->tab_width_combo),
("changed"), (((GCallback) (tab_width_combo_changed))), (window
), ((void*)0), (GConnectFlags) 0)
2039 window)g_signal_connect_data ((window->priv->tab_width_combo),
("changed"), (((GCallback) (tab_width_combo_changed))), (window
), ((void*)0), (GConnectFlags) 0)
;
2040
2041 window->priv->language_combo = pluma_status_combo_box_new (NULL((void*)0));
2042 gtk_widget_show (window->priv->language_combo);
2043 gtk_box_pack_end (GTK_BOX (window->priv->statusbar)((((GtkBox*) (void *) ((window->priv->statusbar))))),
2044 window->priv->language_combo,
2045 FALSE(0),
2046 TRUE(!(0)),
2047 0);
2048
2049 fill_language_combo (window);
2050
2051 g_signal_connect (window->priv->language_combo, "changed",g_signal_connect_data ((window->priv->language_combo), (
"changed"), (((GCallback) (language_combo_changed))), (window
), ((void*)0), (GConnectFlags) 0)
2052 G_CALLBACK (language_combo_changed),g_signal_connect_data ((window->priv->language_combo), (
"changed"), (((GCallback) (language_combo_changed))), (window
), ((void*)0), (GConnectFlags) 0)
2053 window)g_signal_connect_data ((window->priv->language_combo), (
"changed"), (((GCallback) (language_combo_changed))), (window
), ((void*)0), (GConnectFlags) 0)
;
2054
2055 g_signal_connect_after (window->priv->statusbar, "show",g_signal_connect_data ((window->priv->statusbar), ("show"
), (((GCallback) (statusbar_visibility_changed))), (window), (
(void*)0), G_CONNECT_AFTER)
2056 G_CALLBACK (statusbar_visibility_changed),g_signal_connect_data ((window->priv->statusbar), ("show"
), (((GCallback) (statusbar_visibility_changed))), (window), (
(void*)0), G_CONNECT_AFTER)
2057 window)g_signal_connect_data ((window->priv->statusbar), ("show"
), (((GCallback) (statusbar_visibility_changed))), (window), (
(void*)0), G_CONNECT_AFTER)
;
2058 g_signal_connect_after (window->priv->statusbar, "hide",g_signal_connect_data ((window->priv->statusbar), ("hide"
), (((GCallback) (statusbar_visibility_changed))), (window), (
(void*)0), G_CONNECT_AFTER)
2059 G_CALLBACK (statusbar_visibility_changed),g_signal_connect_data ((window->priv->statusbar), ("hide"
), (((GCallback) (statusbar_visibility_changed))), (window), (
(void*)0), G_CONNECT_AFTER)
2060 window)g_signal_connect_data ((window->priv->statusbar), ("hide"
), (((GCallback) (statusbar_visibility_changed))), (window), (
(void*)0), G_CONNECT_AFTER)
;
2061
2062 set_statusbar_style (window, NULL((void*)0));
2063}
2064
2065static PlumaWindow *
2066clone_window (PlumaWindow *origin)
2067{
2068 PlumaWindow *window;
2069 GdkScreen *screen;
2070 PlumaApp *app;
2071 gint panel_page;
2072
2073 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 2073, ((const char*) (__func__
))
);
2074
2075 app = pluma_app_get_default ();
2076
2077 screen = gtk_window_get_screen (GTK_WINDOW (origin)((((GtkWindow*) (void *) ((origin))))));
2078 window = pluma_app_create_window (app, screen);
2079
2080 if ((origin->priv->window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0)
2081 {
2082 gint w, h;
2083
2084 _pluma_window_get_default_size (&w, &h);
2085 gtk_window_set_default_size (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), w, h);
2086 gtk_window_maximize (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
2087 }
2088 else
2089 {
2090 gtk_window_set_default_size (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))),
2091 origin->priv->width,
2092 origin->priv->height);
2093
2094 gtk_window_unmaximize (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
2095 }
2096
2097 if ((origin->priv->window_state & GDK_WINDOW_STATE_STICKY ) != 0)
2098 gtk_window_stick (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
2099 else
2100 gtk_window_unstick (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
2101
2102 /* set the panes size, the paned position will be set when
2103 * they are mapped */
2104 window->priv->side_panel_size = origin->priv->side_panel_size;
2105 window->priv->bottom_panel_size = origin->priv->bottom_panel_size;
2106
2107 panel_page = _pluma_panel_get_active_item_id (PLUMA_PANEL (origin->priv->side_panel)((((PlumaPanel*) (void *) ((origin->priv->side_panel)))
))
);
2108 _pluma_panel_set_active_item_by_id (PLUMA_PANEL (window->priv->side_panel)((((PlumaPanel*) (void *) ((window->priv->side_panel)))
))
, panel_page);
2109
2110 panel_page = _pluma_panel_get_active_item_id (PLUMA_PANEL (origin->priv->bottom_panel)((((PlumaPanel*) (void *) ((origin->priv->bottom_panel)
))))
);
2111 _pluma_panel_set_active_item_by_id (PLUMA_PANEL (window->priv->bottom_panel)((((PlumaPanel*) (void *) ((window->priv->bottom_panel)
))))
, panel_page);
2112
2113 if (gtk_widget_get_visible (origin->priv->side_panel))
2114 gtk_widget_show (window->priv->side_panel);
2115 else
2116 gtk_widget_hide (window->priv->side_panel);
2117
2118 if (gtk_widget_get_visible (origin->priv->bottom_panel))
2119 gtk_widget_show (window->priv->bottom_panel);
2120 else
2121 gtk_widget_hide (window->priv->bottom_panel);
2122
2123 set_statusbar_style (window, origin);
2124 set_toolbar_style (window, origin);
2125
2126 return window;
2127}
2128
2129static void
2130update_cursor_position_statusbar (GtkTextBuffer *buffer,
2131 PlumaWindow *window)
2132{
2133 gint row, col;
2134 GtkTextIter iter;
2135 PlumaView *view;
2136
2137 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 2137, ((const char*) (__func__
))
);
2138
2139 if (buffer != GTK_TEXT_BUFFER (pluma_window_get_active_document (window))((((GtkTextBuffer*) (void *) ((pluma_window_get_active_document
(window))))))
)
2140 return;
2141
2142 view = pluma_window_get_active_view (window);
2143
2144 gtk_text_buffer_get_iter_at_mark (buffer,
2145 &iter,
2146 gtk_text_buffer_get_insert (buffer));
2147
2148 row = gtk_text_iter_get_line (&iter);
2149
2150 col = gtk_source_view_get_visual_column (GTK_SOURCE_VIEW(view)((((GtkSourceView*) (void *) ((view))))), &iter);
2151
2152 pluma_statusbar_set_cursor_position (PLUMA_STATUSBAR (window->priv->statusbar)((((PlumaStatusbar*) (void *) ((window->priv->statusbar
)))))
,
2153 row + 1,
2154 col + 1);
2155}
2156
2157static void
2158update_overwrite_mode_statusbar (GtkTextView *view,
2159 PlumaWindow *window)
2160{
2161 if (view != GTK_TEXT_VIEW (pluma_window_get_active_view (window))((((GtkTextView*) (void *) ((pluma_window_get_active_view (window
))))))
)
2162 return;
2163
2164 /* Note that we have to use !gtk_text_view_get_overwrite since we
2165 are in the in the signal handler of "toggle overwrite" that is
2166 G_SIGNAL_RUN_LAST
2167 */
2168 pluma_statusbar_set_overwrite (PLUMA_STATUSBAR (window->priv->statusbar)((((PlumaStatusbar*) (void *) ((window->priv->statusbar
)))))
,
2169 !gtk_text_view_get_overwrite (view));
2170}
2171
2172#define MAX_TITLE_LENGTH 100
2173
2174static void
2175set_title (PlumaWindow *window)
2176{
2177 PlumaDocument *doc = NULL((void*)0);
2178 gchar *name;
2179 gchar *dirname = NULL((void*)0);
2180 gchar *title = NULL((void*)0);
2181 gint len;
2182 GtkAction *action;
2183
2184 if (window->priv->active_tab == NULL((void*)0))
2185 {
2186 gtk_window_set_title (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), "Pluma");
2187 return;
2188 }
2189
2190 doc = pluma_tab_get_document (window->priv->active_tab);
2191 g_return_if_fail (doc != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_73
; if (doc != ((void*)0)) _g_boolean_var_73 = 1; else _g_boolean_var_73
= 0; _g_boolean_var_73; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "doc != NULL"); return
; } } while (0)
;
2192
2193 name = pluma_document_get_short_name_for_display (doc);
2194
2195 len = g_utf8_strlen (name, -1);
2196
2197 /* if the name is awfully long, truncate it and be done with it,
2198 * otherwise also show the directory (ellipsized if needed)
2199 */
2200 if (len > MAX_TITLE_LENGTH)
2201 {
2202 gchar *tmp;
2203
2204 tmp = pluma_utils_str_middle_truncate (name, MAX_TITLE_LENGTH);
2205 g_free (name);
2206 name = tmp;
2207 }
2208 else
2209 {
2210 GFile *file;
2211
2212 file = pluma_document_get_location (doc);
2213 if (file != NULL((void*)0))
2214 {
2215 gchar *str;
2216
2217 str = pluma_utils_location_get_dirname_for_display (file);
2218 g_object_unref (file);
2219
2220 /* use the remaining space for the dir, but use a min of 20 chars
2221 * so that we do not end up with a dirname like "(a...b)".
2222 * This means that in the worst case when the filename is long 99
2223 * we have a title long 99 + 20, but I think it's a rare enough
2224 * case to be acceptable. It's justa darn title afterall :)
2225 */
2226 dirname = pluma_utils_str_middle_truncate (str, MAX (20, MAX_TITLE_LENGTH - len)(((20) > (MAX_TITLE_LENGTH - len)) ? (20) : (MAX_TITLE_LENGTH
- len))
);
2227 g_free (str);
2228 }
2229 }
2230
2231 if (gtk_text_buffer_get_modified (GTK_TEXT_BUFFER (doc)((((GtkTextBuffer*) (void *) ((doc)))))))
2232 {
2233 gchar *tmp_name;
2234
2235 tmp_name = g_strdup_printf ("*%s", name);
2236 g_free (name);
2237
2238 name = tmp_name;
2239 cansave = TRUE(!(0));
2240 }
2241 else
2242 cansave = FALSE(0);
2243
2244 if (pluma_document_get_readonly (doc))
2245 {
2246 if (dirname != NULL((void*)0))
2247 title = g_strdup_printf ("%s [%s] (%s) - Pluma",
2248 name,
2249 _("Read-Only")dcgettext (((void*)0), "Read-Only", 5),
2250 dirname);
2251 else
2252 title = g_strdup_printf ("%s [%s] - Pluma",
2253 name,
2254 _("Read-Only")dcgettext (((void*)0), "Read-Only", 5));
2255 }
2256 else
2257 {
2258 if (dirname != NULL((void*)0))
2259 title = g_strdup_printf ("%s (%s) - Pluma",
2260 name,
2261 dirname);
2262 else
2263 title = g_strdup_printf ("%s - Pluma",
2264 name);
2265 }
2266
2267 action = gtk_action_group_get_action (window->priv->action_group, "FileSave");
2268 gtk_action_set_sensitive (action, cansave);
2269
2270 gtk_window_set_title (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))), title);
2271
2272 g_free (dirname);
2273 g_free (name);
2274 g_free (title);
2275}
2276
2277#undef MAX_TITLE_LENGTH
2278
2279static void
2280set_tab_width_item_blocked (PlumaWindow *window,
2281 GtkMenuItem *item)
2282{
2283 g_signal_handlers_block_by_func (window->priv->tab_width_combo,g_signal_handlers_block_matched ((window->priv->tab_width_combo
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (tab_width_combo_changed), (window))
2284 tab_width_combo_changed,g_signal_handlers_block_matched ((window->priv->tab_width_combo
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (tab_width_combo_changed), (window))
2285 window)g_signal_handlers_block_matched ((window->priv->tab_width_combo
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (tab_width_combo_changed), (window))
;
2286
2287 pluma_status_combo_box_set_item (PLUMA_STATUS_COMBO_BOX (window->priv->tab_width_combo)((((PlumaStatusComboBox*) (void *) ((window->priv->tab_width_combo
)))))
,
2288 item);
2289
2290 g_signal_handlers_unblock_by_func (window->priv->tab_width_combo,g_signal_handlers_unblock_matched ((window->priv->tab_width_combo
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (tab_width_combo_changed), (window))
2291 tab_width_combo_changed,g_signal_handlers_unblock_matched ((window->priv->tab_width_combo
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (tab_width_combo_changed), (window))
2292 window)g_signal_handlers_unblock_matched ((window->priv->tab_width_combo
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (tab_width_combo_changed), (window))
;
2293}
2294
2295static void
2296spaces_instead_of_tabs_changed (GObject *object,
2297 GParamSpec *pspec,
2298 PlumaWindow *window)
2299{
2300 PlumaView *view = PLUMA_VIEW (object)((((PlumaView*) (void *) ((object)))));
2301 gboolean active = gtk_source_view_get_insert_spaces_instead_of_tabs (GTK_SOURCE_VIEW (view)((((GtkSourceView*) (void *) ((view))))));
2302 GList *children = pluma_status_combo_box_get_items (PLUMA_STATUS_COMBO_BOX (window->priv->tab_width_combo)((((PlumaStatusComboBox*) (void *) ((window->priv->tab_width_combo
)))))
);
2303 GtkCheckMenuItem *item;
2304
2305 item = GTK_CHECK_MENU_ITEM (g_list_last (children)->data)((((GtkCheckMenuItem*) (void *) ((g_list_last (children)->
data)))))
;
2306
2307 gtk_check_menu_item_set_active (item, active);
2308
2309 g_list_free (children);
2310}
2311
2312static void
2313tab_width_changed (GObject *object,
2314 GParamSpec *pspec,
2315 PlumaWindow *window)
2316{
2317 GList *items;
2318 GList *item;
2319 PlumaStatusComboBox *combo = PLUMA_STATUS_COMBO_BOX (window->priv->tab_width_combo)((((PlumaStatusComboBox*) (void *) ((window->priv->tab_width_combo
)))))
;
2320 guint new_tab_width;
2321 gboolean found = FALSE(0);
2322
2323 items = pluma_status_combo_box_get_items (combo);
2324
2325 new_tab_width = gtk_source_view_get_tab_width (GTK_SOURCE_VIEW (object)((((GtkSourceView*) (void *) ((object))))));
2326
2327 for (item = items; item; item = item->next)
2328 {
2329 guint tab_width = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (item->data), TAB_WIDTH_DATA))((gint) (glong) (g_object_get_data (((((GObject*) (void *) ((
item->data))))), "PlumaWindowTabWidthData")))
;
2330
2331 if (tab_width == new_tab_width)
2332 {
2333 set_tab_width_item_blocked (window, GTK_MENU_ITEM (item->data)((((GtkMenuItem*) (void *) ((item->data))))));
2334 found = TRUE(!(0));
2335 }
2336
2337 if (GTK_IS_SEPARATOR_MENU_ITEM (item->next->data)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(item->next->data)); GType __t = ((gtk_separator_menu_item_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
2338 {
2339 if (!found)
2340 {
2341 /* Set for the last item the custom thing */
2342 gchar *text;
2343
2344 text = g_strdup_printf ("%u", new_tab_width);
2345 pluma_status_combo_box_set_item_text (combo,
2346 GTK_MENU_ITEM (item->data)((((GtkMenuItem*) (void *) ((item->data))))),
2347 text);
2348
2349 gtk_label_set_text (GTK_LABEL (gtk_bin_get_child (GTK_BIN (item->data)))((((GtkLabel*) (void *) ((gtk_bin_get_child (((((GtkBin*) (void
*) ((item->data)))))))))))
,
2350 text);
2351
2352 set_tab_width_item_blocked (window, GTK_MENU_ITEM (item->data)((((GtkMenuItem*) (void *) ((item->data))))));
2353 gtk_widget_show (GTK_WIDGET (item->data)((((GtkWidget*) (void *) ((item->data))))));
2354 }
2355 else
2356 {
2357 gtk_widget_hide (GTK_WIDGET (item->data)((((GtkWidget*) (void *) ((item->data))))));
2358 }
2359
2360 break;
2361 }
2362 }
2363
2364 g_list_free (items);
2365}
2366
2367static void
2368language_changed (GObject *object,
2369 GParamSpec *pspec,
2370 PlumaWindow *window)
2371{
2372 GList *items;
2373 GList *item;
2374 PlumaStatusComboBox *combo = PLUMA_STATUS_COMBO_BOX (window->priv->language_combo)((((PlumaStatusComboBox*) (void *) ((window->priv->language_combo
)))))
;
2375 GtkSourceLanguage *new_language;
2376 const gchar *new_id;
2377
2378 items = pluma_status_combo_box_get_items (combo);
2379
2380 new_language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (object)((((GtkSourceBuffer*) (void *) ((object))))));
2381
2382 if (new_language)
2383 new_id = gtk_source_language_get_id (new_language);
2384 else
2385 new_id = NULL((void*)0);
2386
2387 for (item = items; item; item = item->next)
2388 {
2389 GtkSourceLanguage *lang = g_object_get_data (G_OBJECT (item->data)((((GObject*) (void *) ((item->data))))), LANGUAGE_DATA"PlumaWindowLanguageData");
2390
2391 if ((new_id == NULL((void*)0) && lang == NULL((void*)0)) ||
2392 (new_id != NULL((void*)0) && lang != NULL((void*)0) && strcmp (gtk_source_language_get_id (lang), new_id) == 0))
2393 {
2394 g_signal_handlers_block_by_func (window->priv->language_combo,g_signal_handlers_block_matched ((window->priv->language_combo
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (language_combo_changed), (window))
2395 language_combo_changed,g_signal_handlers_block_matched ((window->priv->language_combo
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (language_combo_changed), (window))
2396 window)g_signal_handlers_block_matched ((window->priv->language_combo
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (language_combo_changed), (window))
;
2397
2398 pluma_status_combo_box_set_item (PLUMA_STATUS_COMBO_BOX (window->priv->language_combo)((((PlumaStatusComboBox*) (void *) ((window->priv->language_combo
)))))
,
2399 GTK_MENU_ITEM (item->data)((((GtkMenuItem*) (void *) ((item->data))))));
2400
2401 g_signal_handlers_unblock_by_func (window->priv->language_combo,g_signal_handlers_unblock_matched ((window->priv->language_combo
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (language_combo_changed), (window))
2402 language_combo_changed,g_signal_handlers_unblock_matched ((window->priv->language_combo
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (language_combo_changed), (window))
2403 window)g_signal_handlers_unblock_matched ((window->priv->language_combo
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (language_combo_changed), (window))
;
2404 }
2405 }
2406
2407 g_list_free (items);
2408}
2409
2410static void
2411notebook_switch_page (GtkNotebook *book,
2412 GtkWidget *pg,
2413 gint page_num,
2414 PlumaWindow *window)
2415{
2416 PlumaView *view;
2417 PlumaTab *tab;
2418 GtkAction *action;
2419 gchar *action_name;
2420
2421 /* CHECK: I don't know why but it seems notebook_switch_page is called
2422 two times every time the user change the active tab */
2423
2424 tab = PLUMA_TAB (gtk_notebook_get_nth_page (book, page_num))((((PlumaTab*) (void *) ((gtk_notebook_get_nth_page (book, page_num
))))))
;
2425 if (tab == window->priv->active_tab)
2426 return;
2427
2428 if (window->priv->active_tab)
2429 {
2430#if GLIB_CHECK_VERSION(2,62,0)(2 > (2) || (2 == (2) && 76 > (62)) || (2 == (2
) && 76 == (62) && 5 >= (0)))
2431 PlumaView *active_tab_view;
2432
2433 active_tab_view = pluma_tab_get_view (window->priv->active_tab);
2434 g_clear_signal_handler (&window->priv->tab_width_id,do { gpointer const _instance = (active_tab_view); gulong *const
_handler_id_ptr = (&window->priv->tab_width_id); const
gulong _handler_id = *_handler_id_ptr; if (_handler_id > 0
) { *_handler_id_ptr = 0; g_signal_handler_disconnect (_instance
, _handler_id); } } while (0)
2435 active_tab_view)do { gpointer const _instance = (active_tab_view); gulong *const
_handler_id_ptr = (&window->priv->tab_width_id); const
gulong _handler_id = *_handler_id_ptr; if (_handler_id > 0
) { *_handler_id_ptr = 0; g_signal_handler_disconnect (_instance
, _handler_id); } } while (0)
;
2436 g_clear_signal_handler (&window->priv->spaces_instead_of_tabs_id,do { gpointer const _instance = (active_tab_view); gulong *const
_handler_id_ptr = (&window->priv->spaces_instead_of_tabs_id
); const gulong _handler_id = *_handler_id_ptr; if (_handler_id
> 0) { *_handler_id_ptr = 0; g_signal_handler_disconnect (
_instance, _handler_id); } } while (0)
2437 active_tab_view)do { gpointer const _instance = (active_tab_view); gulong *const
_handler_id_ptr = (&window->priv->spaces_instead_of_tabs_id
); const gulong _handler_id = *_handler_id_ptr; if (_handler_id
> 0) { *_handler_id_ptr = 0; g_signal_handler_disconnect (
_instance, _handler_id); } } while (0)
;
2438#else
2439 if (window->priv->tab_width_id)
2440 {
2441 g_signal_handler_disconnect (pluma_tab_get_view (window->priv->active_tab),
2442 window->priv->tab_width_id);
2443
2444 window->priv->tab_width_id = 0;
2445 }
2446
2447 if (window->priv->spaces_instead_of_tabs_id)
2448 {
2449 g_signal_handler_disconnect (pluma_tab_get_view (window->priv->active_tab),
2450 window->priv->spaces_instead_of_tabs_id);
2451
2452 window->priv->spaces_instead_of_tabs_id = 0;
2453 }
2454#endif
2455 }
2456
2457 /* set the active tab */
2458 window->priv->active_tab = tab;
2459
2460 set_title (window);
2461 set_sensitivity_according_to_tab (window, tab);
2462
2463 /* activate the right item in the documents menu */
2464 action_name = g_strdup_printf ("Tab_%d", page_num);
2465 action = gtk_action_group_get_action (window->priv->documents_list_action_group,
2466 action_name);
2467
2468 /* sometimes the action doesn't exist yet, and the proper action
2469 * is set active during the documents list menu creation
2470 * CHECK: would it be nicer if active_tab was a property and we monitored the notify signal?
2471 */
2472 if (action != NULL((void*)0))
2473 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action))))), TRUE(!(0)));
2474
2475 g_free (action_name);
2476
2477 /* update the syntax menu */
2478 update_languages_menu (window);
2479
2480 view = pluma_tab_get_view (tab);
2481
2482 /* sync the statusbar */
2483 update_cursor_position_statusbar (GTK_TEXT_BUFFER (pluma_tab_get_document (tab))((((GtkTextBuffer*) (void *) ((pluma_tab_get_document (tab)))
)))
,
2484 window);
2485 pluma_statusbar_set_overwrite (PLUMA_STATUSBAR (window->priv->statusbar)((((PlumaStatusbar*) (void *) ((window->priv->statusbar
)))))
,
2486 gtk_text_view_get_overwrite (GTK_TEXT_VIEW (view)((((GtkTextView*) (void *) ((view)))))));
2487
2488 gtk_widget_show (window->priv->tab_width_combo);
2489 gtk_widget_show (window->priv->language_combo);
2490
2491 window->priv->tab_width_id = g_signal_connect (view,g_signal_connect_data ((view), ("notify::tab-width"), (((GCallback
) (tab_width_changed))), (window), ((void*)0), (GConnectFlags
) 0)
2492 "notify::tab-width",g_signal_connect_data ((view), ("notify::tab-width"), (((GCallback
) (tab_width_changed))), (window), ((void*)0), (GConnectFlags
) 0)
2493 G_CALLBACK (tab_width_changed),g_signal_connect_data ((view), ("notify::tab-width"), (((GCallback
) (tab_width_changed))), (window), ((void*)0), (GConnectFlags
) 0)
2494 window)g_signal_connect_data ((view), ("notify::tab-width"), (((GCallback
) (tab_width_changed))), (window), ((void*)0), (GConnectFlags
) 0)
;
2495 window->priv->spaces_instead_of_tabs_id = g_signal_connect (view,g_signal_connect_data ((view), ("notify::insert-spaces-instead-of-tabs"
), (((GCallback) (spaces_instead_of_tabs_changed))), (window)
, ((void*)0), (GConnectFlags) 0)
2496 "notify::insert-spaces-instead-of-tabs",g_signal_connect_data ((view), ("notify::insert-spaces-instead-of-tabs"
), (((GCallback) (spaces_instead_of_tabs_changed))), (window)
, ((void*)0), (GConnectFlags) 0)
2497 G_CALLBACK (spaces_instead_of_tabs_changed),g_signal_connect_data ((view), ("notify::insert-spaces-instead-of-tabs"
), (((GCallback) (spaces_instead_of_tabs_changed))), (window)
, ((void*)0), (GConnectFlags) 0)
2498 window)g_signal_connect_data ((view), ("notify::insert-spaces-instead-of-tabs"
), (((GCallback) (spaces_instead_of_tabs_changed))), (window)
, ((void*)0), (GConnectFlags) 0)
;
2499
2500 window->priv->language_changed_id = g_signal_connect (pluma_tab_get_document (tab),g_signal_connect_data ((pluma_tab_get_document (tab)), ("notify::language"
), (((GCallback) (language_changed))), (window), ((void*)0), (
GConnectFlags) 0)
2501 "notify::language",g_signal_connect_data ((pluma_tab_get_document (tab)), ("notify::language"
), (((GCallback) (language_changed))), (window), ((void*)0), (
GConnectFlags) 0)
2502 G_CALLBACK (language_changed),g_signal_connect_data ((pluma_tab_get_document (tab)), ("notify::language"
), (((GCallback) (language_changed))), (window), ((void*)0), (
GConnectFlags) 0)
2503 window)g_signal_connect_data ((pluma_tab_get_document (tab)), ("notify::language"
), (((GCallback) (language_changed))), (window), ((void*)0), (
GConnectFlags) 0)
;
2504
2505 /* call it for the first time */
2506 tab_width_changed (G_OBJECT (view)((((GObject*) (void *) ((view))))), NULL((void*)0), window);
2507 spaces_instead_of_tabs_changed (G_OBJECT (view)((((GObject*) (void *) ((view))))), NULL((void*)0), window);
2508 language_changed (G_OBJECT (pluma_tab_get_document (tab))((((GObject*) (void *) ((pluma_tab_get_document (tab)))))), NULL((void*)0), window);
2509
2510 g_signal_emit (G_OBJECT (window)((((GObject*) (void *) ((window))))),
2511 signals[ACTIVE_TAB_CHANGED],
2512 0,
2513 window->priv->active_tab);
2514}
2515
2516static void
2517set_sensitivity_according_to_window_state (PlumaWindow *window)
2518{
2519 GtkAction *action;
2520 PlumaLockdownMask lockdown;
2521
2522 lockdown = pluma_app_get_lockdown (pluma_app_get_default ());
2523
2524 /* We disable File->Quit/SaveAll/CloseAll while printing to avoid to have two
2525 operations (save and print/print preview) that uses the message area at
2526 the same time (may be we can remove this limitation in the future) */
2527 /* We disable File->Quit/CloseAll if state is saving since saving cannot be
2528 cancelled (may be we can remove this limitation in the future) */
2529 gtk_action_group_set_sensitive (window->priv->quit_action_group,
2530 !(window->priv->state & PLUMA_WINDOW_STATE_SAVING) &&
2531 !(window->priv->state & PLUMA_WINDOW_STATE_PRINTING));
2532
2533 action = gtk_action_group_get_action (window->priv->action_group,
2534 "FileCloseAll");
2535 gtk_action_set_sensitive (action,
2536 !(window->priv->state & PLUMA_WINDOW_STATE_SAVING) &&
2537 !(window->priv->state & PLUMA_WINDOW_STATE_PRINTING));
2538
2539 action = gtk_action_group_get_action (window->priv->action_group,
2540 "FileSaveAll");
2541 gtk_action_set_sensitive (action,
2542 !(window->priv->state & PLUMA_WINDOW_STATE_PRINTING) &&
2543 !(lockdown & PLUMA_LOCKDOWN_SAVE_TO_DISK));
2544
2545 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group,
2546 "FileNew");
2547 gtk_action_set_sensitive (action,
2548 !(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION));
2549
2550 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group,
2551 "FileOpen");
2552 gtk_action_set_sensitive (action,
2553 !(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION));
2554
2555 gtk_action_group_set_sensitive (window->priv->recents_action_group,
2556 !(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION));
2557
2558 pluma_notebook_set_close_buttons_sensitive (PLUMA_NOTEBOOK (window->priv->notebook)((((PlumaNotebook*) (void *) ((window->priv->notebook))
)))
,
2559 !(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION));
2560
2561 pluma_notebook_set_tab_drag_and_drop_enabled (PLUMA_NOTEBOOK (window->priv->notebook)((((PlumaNotebook*) (void *) ((window->priv->notebook))
)))
,
2562 !(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION));
2563
2564 if ((window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION) != 0)
2565 {
2566 /* TODO: If we really care, Find could be active
2567 * when in SAVING_SESSION state */
2568
2569 if (gtk_action_group_get_sensitive (window->priv->action_group))
2570 gtk_action_group_set_sensitive (window->priv->action_group, FALSE(0));
2571
2572 if (gtk_action_group_get_sensitive (window->priv->quit_action_group))
2573 gtk_action_group_set_sensitive (window->priv->quit_action_group, FALSE(0));
2574
2575 if (gtk_action_group_get_sensitive (window->priv->close_action_group))
2576 gtk_action_group_set_sensitive (window->priv->close_action_group, FALSE(0));
2577 }
2578 else
2579 {
2580 if (!gtk_action_group_get_sensitive (window->priv->action_group))
2581 gtk_action_group_set_sensitive (window->priv->action_group, window->priv->num_tabs > 0);
2582
2583 if (!gtk_action_group_get_sensitive (window->priv->quit_action_group))
2584 gtk_action_group_set_sensitive (window->priv->quit_action_group, window->priv->num_tabs > 0);
2585
2586 if (!gtk_action_group_get_sensitive (window->priv->close_action_group))
2587 gtk_action_group_set_sensitive (window->priv->close_action_group, window->priv->num_tabs > 0);
2588 }
2589}
2590
2591static void
2592update_tab_autosave (GtkWidget *widget,
2593 gpointer data)
2594{
2595 PlumaTab *tab = PLUMA_TAB (widget)((((PlumaTab*) (void *) ((widget)))));
2596 gboolean *enabled = (gboolean *) data;
2597
2598 pluma_tab_set_auto_save_enabled (tab, *enabled);
2599}
2600
2601void
2602_pluma_window_set_lockdown (PlumaWindow *window,
2603 PlumaLockdownMask lockdown)
2604{
2605 PlumaTab *tab;
2606 GtkAction *action;
2607 gboolean autosave;
2608
2609 /* start/stop autosave in each existing tab */
2610 autosave = g_settings_get_boolean (window->priv->editor_settings, PLUMA_SETTINGS_AUTO_SAVE"auto-save");
2611 gtk_container_foreach (GTK_CONTAINER (window->priv->notebook)((((GtkContainer*) (void *) ((window->priv->notebook)))
))
,
2612 update_tab_autosave,
2613 &autosave);
2614
2615 /* update menues wrt the current active tab */
2616 tab = pluma_window_get_active_tab (window);
2617
2618 set_sensitivity_according_to_tab (window, tab);
2619
2620 action = gtk_action_group_get_action (window->priv->action_group,
2621 "FileSaveAll");
2622 gtk_action_set_sensitive (action,
2623 !(window->priv->state & PLUMA_WINDOW_STATE_PRINTING) &&
2624 !(lockdown & PLUMA_LOCKDOWN_SAVE_TO_DISK));
2625
2626}
2627
2628static void
2629analyze_tab_state (PlumaTab *tab,
2630 PlumaWindow *window)
2631{
2632 PlumaTabState ts;
2633
2634 ts = pluma_tab_get_state (tab);
2635
2636 switch (ts)
2637 {
2638 case PLUMA_TAB_STATE_LOADING:
2639 case PLUMA_TAB_STATE_REVERTING:
2640 window->priv->state |= PLUMA_WINDOW_STATE_LOADING;
2641 break;
2642
2643 case PLUMA_TAB_STATE_SAVING:
2644 window->priv->state |= PLUMA_WINDOW_STATE_SAVING;
2645 break;
2646
2647 case PLUMA_TAB_STATE_PRINTING:
2648 case PLUMA_TAB_STATE_PRINT_PREVIEWING:
2649 window->priv->state |= PLUMA_WINDOW_STATE_PRINTING;
2650 break;
2651
2652 case PLUMA_TAB_STATE_LOADING_ERROR:
2653 case PLUMA_TAB_STATE_REVERTING_ERROR:
2654 case PLUMA_TAB_STATE_SAVING_ERROR:
2655 case PLUMA_TAB_STATE_GENERIC_ERROR:
2656 window->priv->state |= PLUMA_WINDOW_STATE_ERROR;
2657 ++window->priv->num_tabs_with_error;
2658 default:
2659 /* NOP */
2660 break;
2661 }
2662}
2663
2664static void
2665update_window_state (PlumaWindow *window)
2666{
2667 PlumaWindowState old_ws;
2668 gint old_num_of_errors;
2669
2670 pluma_debug_message (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 2670, ((const char*) (__func__
))
, "Old state: %x", window->priv->state);
2671
2672 old_ws = window->priv->state;
2673 old_num_of_errors = window->priv->num_tabs_with_error;
2674
2675 window->priv->state = old_ws & PLUMA_WINDOW_STATE_SAVING_SESSION;
2676
2677 window->priv->num_tabs_with_error = 0;
2678
2679 gtk_container_foreach (GTK_CONTAINER (window->priv->notebook)((((GtkContainer*) (void *) ((window->priv->notebook)))
))
,
2680 (GtkCallback)analyze_tab_state,
2681 window);
2682
2683 pluma_debug_message (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 2683, ((const char*) (__func__
))
, "New state: %x", window->priv->state);
2684
2685 if (old_ws != window->priv->state)
2686 {
2687 set_sensitivity_according_to_window_state (window);
2688
2689 pluma_statusbar_set_window_state (PLUMA_STATUSBAR (window->priv->statusbar)((((PlumaStatusbar*) (void *) ((window->priv->statusbar
)))))
,
2690 window->priv->state,
2691 window->priv->num_tabs_with_error);
2692
2693 g_object_notify (G_OBJECT (window)((((GObject*) (void *) ((window))))), "state");
2694 }
2695 else if (old_num_of_errors != window->priv->num_tabs_with_error)
2696 {
2697 pluma_statusbar_set_window_state (PLUMA_STATUSBAR (window->priv->statusbar)((((PlumaStatusbar*) (void *) ((window->priv->statusbar
)))))
,
2698 window->priv->state,
2699 window->priv->num_tabs_with_error);
2700 }
2701}
2702
2703static void
2704sync_state (PlumaTab *tab,
2705 GParamSpec *pspec,
2706 PlumaWindow *window)
2707{
2708 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 2708, ((const char*) (__func__
))
);
2709
2710 update_window_state (window);
2711
2712 if (tab != window->priv->active_tab)
2713 return;
2714
2715 set_sensitivity_according_to_tab (window, tab);
2716
2717 g_signal_emit (G_OBJECT (window)((((GObject*) (void *) ((window))))), signals[ACTIVE_TAB_STATE_CHANGED], 0);
2718}
2719
2720static void
2721sync_name (PlumaTab *tab,
2722 GParamSpec *pspec,
2723 PlumaWindow *window)
2724{
2725 GtkAction *action;
2726 gchar *action_name;
2727 gchar *tab_name;
2728 gchar *escaped_name;
2729 gchar *tip;
2730 gint n;
2731 PlumaDocument *doc;
2732
2733 if (tab == window->priv->active_tab)
2734 {
2735 set_title (window);
2736
2737 doc = pluma_tab_get_document (tab);
2738 action = gtk_action_group_get_action (window->priv->action_group,
2739 "FileRevert");
2740 gtk_action_set_sensitive (action, !pluma_document_is_untitled (doc));
2741 }
2742
2743 /* sync the item in the documents list menu */
2744 n = gtk_notebook_page_num (GTK_NOTEBOOK (window->priv->notebook)((((GtkNotebook*) (void *) ((window->priv->notebook))))
)
, GTK_WIDGET (tab)((((GtkWidget*) (void *) ((tab))))));
2745
2746 action_name = g_strdup_printf ("Tab_%d", n);
2747 action = gtk_action_group_get_action (window->priv->documents_list_action_group,
2748 action_name);
2749 g_free (action_name);
2750 g_return_if_fail (action != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_74
; if (action != ((void*)0)) _g_boolean_var_74 = 1; else _g_boolean_var_74
= 0; _g_boolean_var_74; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "action != NULL")
; return; } } while (0)
;
2751
2752 tab_name = _pluma_tab_get_name (tab);
2753 escaped_name = pluma_utils_escape_underscores (tab_name, -1);
2754 tip = get_menu_tip_for_tab (tab);
2755
2756 g_object_set (action, "label", escaped_name, NULL((void*)0));
2757 g_object_set (action, "tooltip", tip, NULL((void*)0));
2758
2759 g_free (tab_name);
2760 g_free (escaped_name);
2761 g_free (tip);
2762
2763 peas_extension_set_call (window->priv->extensions, "update_state");
2764}
2765
2766static PlumaWindow *
2767get_drop_window (GtkWidget *widget)
2768{
2769 GtkWidget *target_window;
2770
2771 target_window = gtk_widget_get_toplevel (widget);
2772 g_return_val_if_fail (PLUMA_IS_WINDOW (target_window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_75
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((target_window)); GType __t = ((pluma_window_get_type()))
; gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class
&& __inst->g_class->g_type == __t) __r = (!(0)
); else __r = g_type_check_instance_is_a (__inst, __t); __r; }
))))) _g_boolean_var_75 = 1; else _g_boolean_var_75 = 0; _g_boolean_var_75
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "PLUMA_IS_WINDOW (target_window)"
); return (((void*)0)); } } while (0)
;
2773
2774 if ((PLUMA_WINDOW(target_window)((((PlumaWindow*) (void *) ((target_window)))))->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION) != 0)
2775 return NULL((void*)0);
2776
2777 return PLUMA_WINDOW (target_window)((((PlumaWindow*) (void *) ((target_window)))));
2778}
2779
2780static void
2781load_uris_from_drop (PlumaWindow *window,
2782 gchar **uri_list)
2783{
2784 GSList *uris = NULL((void*)0);
2785 gint i;
2786
2787 if (uri_list == NULL((void*)0))
2788 return;
2789
2790 for (i = 0; uri_list[i] != NULL((void*)0); ++i)
2791 {
2792 uris = g_slist_prepend (uris, uri_list[i]);
2793 }
2794
2795 uris = g_slist_reverse (uris);
2796 pluma_commands_load_uris (window,
2797 uris,
2798 NULL((void*)0),
2799 0);
2800
2801 g_slist_free (uris);
2802}
2803
2804/* Handle drops on the PlumaWindow */
2805static void
2806drag_data_received_cb (GtkWidget *widget,
2807 GdkDragContext *context,
2808 gint x,
2809 gint y,
2810 GtkSelectionData *selection_data,
2811 guint info,
2812 guint timestamp,
2813 gpointer data)
2814{
2815 PlumaWindow *window;
2816 gchar **uri_list;
2817
2818 window = get_drop_window (widget);
2819
2820 if (window == NULL((void*)0))
2821 return;
2822
2823 if (info == TARGET_URI_LIST)
2824 {
2825 uri_list = pluma_utils_drop_get_uris(selection_data);
2826 load_uris_from_drop (window, uri_list);
2827 g_strfreev (uri_list);
2828 }
2829}
2830
2831/* Handle drops on the PlumaView */
2832static void
2833drop_uris_cb (GtkWidget *widget,
2834 gchar **uri_list)
2835{
2836 PlumaWindow *window;
2837
2838 window = get_drop_window (widget);
2839
2840 if (window == NULL((void*)0))
2841 return;
2842
2843 load_uris_from_drop (window, uri_list);
2844}
2845
2846static void
2847fullscreen_controls_show (PlumaWindow *window)
2848{
2849 GdkScreen *screen;
2850 GdkDisplay *display;
2851 GdkRectangle fs_rect;
2852 gint w, h;
2853
2854 screen = gtk_window_get_screen (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
2855 display = gdk_screen_get_display (screen);
2856
2857 gdk_monitor_get_geometry (gdk_display_get_monitor_at_window (display,
2858 gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))))),
2859 &fs_rect);
2860
2861 gtk_window_get_size (GTK_WINDOW (window->priv->fullscreen_controls)((((GtkWindow*) (void *) ((window->priv->fullscreen_controls
)))))
, &w, &h);
2862
2863 gtk_window_resize (GTK_WINDOW (window->priv->fullscreen_controls)((((GtkWindow*) (void *) ((window->priv->fullscreen_controls
)))))
,
2864 fs_rect.width, h);
2865
2866 gtk_window_move (GTK_WINDOW (window->priv->fullscreen_controls)((((GtkWindow*) (void *) ((window->priv->fullscreen_controls
)))))
,
2867 fs_rect.x, fs_rect.y - h + 1);
2868
2869 gtk_widget_show_all (window->priv->fullscreen_controls);
2870}
2871
2872static gboolean
2873run_fullscreen_animation (gpointer data)
2874{
2875 PlumaWindow *window = PLUMA_WINDOW (data)((((PlumaWindow*) (void *) ((data)))));
2876 GdkScreen *screen;
2877 GdkDisplay *display;
2878 GdkRectangle fs_rect;
2879 gint x, y;
2880
2881 screen = gtk_window_get_screen (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
2882 display = gdk_screen_get_display (screen);
2883
2884 gdk_monitor_get_geometry (gdk_display_get_monitor_at_window (display,
2885 gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))))),
2886 &fs_rect);
2887
2888 gtk_window_get_position (GTK_WINDOW (window->priv->fullscreen_controls)((((GtkWindow*) (void *) ((window->priv->fullscreen_controls
)))))
,
2889 &x,
2890 &y);
2891
2892 if (window->priv->fullscreen_animation_enter)
2893 {
2894 if (y == fs_rect.y)
2895 {
2896 window->priv->fullscreen_animation_timeout_id = 0;
2897 return FALSE(0);
2898 }
2899 else
2900 {
2901 gtk_window_move (GTK_WINDOW (window->priv->fullscreen_controls)((((GtkWindow*) (void *) ((window->priv->fullscreen_controls
)))))
,
2902 x, y + 1);
2903 return TRUE(!(0));
2904 }
2905 }
2906 else
2907 {
2908 gint w, h;
2909
2910 gtk_window_get_size (GTK_WINDOW (window->priv->fullscreen_controls)((((GtkWindow*) (void *) ((window->priv->fullscreen_controls
)))))
,
2911 &w, &h);
2912
2913 if (y == fs_rect.y - h + 1)
2914 {
2915 window->priv->fullscreen_animation_timeout_id = 0;
2916 return FALSE(0);
2917 }
2918 else
2919 {
2920 gtk_window_move (GTK_WINDOW (window->priv->fullscreen_controls)((((GtkWindow*) (void *) ((window->priv->fullscreen_controls
)))))
,
2921 x, y - 1);
2922 return TRUE(!(0));
2923 }
2924 }
2925}
2926
2927static void
2928show_hide_fullscreen_toolbar (PlumaWindow *window,
2929 gboolean show,
2930 gint height)
2931{
2932 GtkSettings *settings;
2933 gboolean enable_animations;
2934
2935 settings = gtk_widget_get_settings (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
2936 g_object_get (G_OBJECT (settings)((((GObject*) (void *) ((settings))))),
2937 "gtk-enable-animations",
2938 &enable_animations,
2939 NULL((void*)0));
2940
2941 if (enable_animations)
2942 {
2943 window->priv->fullscreen_animation_enter = show;
2944
2945 if (window->priv->fullscreen_animation_timeout_id == 0)
2946 {
2947 window->priv->fullscreen_animation_timeout_id =
2948 g_timeout_add (FULLSCREEN_ANIMATION_SPEED4,
2949 (GSourceFunc) run_fullscreen_animation,
2950 window);
2951 }
2952 }
2953 else
2954 {
2955 GdkRectangle fs_rect;
2956 GdkScreen *screen;
2957 GdkDisplay *display;
2958
2959 screen = gtk_window_get_screen (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
2960 display = gdk_screen_get_display (screen);
2961
2962 gdk_monitor_get_geometry (gdk_display_get_monitor_at_window (display,
2963 gtk_widget_get_window (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))))),
2964 &fs_rect);
2965
2966 if (show)
2967 gtk_window_move (GTK_WINDOW (window->priv->fullscreen_controls)((((GtkWindow*) (void *) ((window->priv->fullscreen_controls
)))))
,
2968 fs_rect.x, fs_rect.y);
2969 else
2970 gtk_window_move (GTK_WINDOW (window->priv->fullscreen_controls)((((GtkWindow*) (void *) ((window->priv->fullscreen_controls
)))))
,
2971 fs_rect.x, fs_rect.y - height + 1);
2972 }
2973
2974}
2975
2976static gboolean
2977on_fullscreen_controls_enter_notify_event (GtkWidget *widget,
2978 GdkEventCrossing *event,
2979 PlumaWindow *window)
2980{
2981 show_hide_fullscreen_toolbar (window, TRUE(!(0)), 0);
2982
2983 return FALSE(0);
2984}
2985
2986static gboolean
2987on_fullscreen_controls_leave_notify_event (GtkWidget *widget,
2988 GdkEventCrossing *event,
2989 PlumaWindow *window)
2990{
2991 GdkDevice *device;
2992 gint w, h;
2993 gint x, y;
2994
2995 device = gdk_event_get_device ((GdkEvent *)event);
2996
2997 gtk_window_get_size (GTK_WINDOW (window->priv->fullscreen_controls)((((GtkWindow*) (void *) ((window->priv->fullscreen_controls
)))))
, &w, &h);
2998 gdk_device_get_position (device, NULL((void*)0), &x, &y);
2999
3000 /* gtk seems to emit leave notify when clicking on tool items,
3001 * work around it by checking the coordinates
3002 */
3003 if (y >= h)
3004 {
3005 show_hide_fullscreen_toolbar (window, FALSE(0), h);
3006 }
3007
3008 return FALSE(0);
3009}
3010
3011static void
3012fullscreen_controls_build (PlumaWindow *window)
3013{
3014 PlumaWindowPrivate *priv = window->priv;
3015 GtkWidget *toolbar;
3016 GtkAction *action;
3017
3018 if (priv->fullscreen_controls != NULL((void*)0))
3019 return;
3020
3021 priv->fullscreen_controls = gtk_window_new (GTK_WINDOW_POPUP);
3022
3023 gtk_window_set_transient_for (GTK_WINDOW (priv->fullscreen_controls)((((GtkWindow*) (void *) ((priv->fullscreen_controls))))),
3024 &window->window);
3025
3026 /* popup toolbar */
3027 toolbar = gtk_ui_manager_get_widget (priv->manager, "/FullscreenToolBar");
3028 gtk_container_add (GTK_CONTAINER (priv->fullscreen_controls)((((GtkContainer*) (void *) ((priv->fullscreen_controls)))
))
, toolbar);
3029
3030 action = gtk_action_group_get_action (priv->always_sensitive_action_group,
3031 "LeaveFullscreen");
3032 g_object_set (action, "is-important", TRUE(!(0)), NULL((void*)0));
3033
3034 setup_toolbar_open_button (window, toolbar);
3035
3036 gtk_container_foreach (GTK_CONTAINER (toolbar)((((GtkContainer*) (void *) ((toolbar))))),
3037 (GtkCallback)set_non_homogeneus,
3038 NULL((void*)0));
3039
3040 /* Set the toolbar style */
3041 gtk_toolbar_set_style (GTK_TOOLBAR (toolbar)((((GtkToolbar*) (void *) ((toolbar))))), GTK_TOOLBAR_BOTH_HORIZ);
3042
3043 g_signal_connect (priv->fullscreen_controls, "enter-notify-event",g_signal_connect_data ((priv->fullscreen_controls), ("enter-notify-event"
), (((GCallback) (on_fullscreen_controls_enter_notify_event))
), (window), ((void*)0), (GConnectFlags) 0)
3044 G_CALLBACK (on_fullscreen_controls_enter_notify_event),g_signal_connect_data ((priv->fullscreen_controls), ("enter-notify-event"
), (((GCallback) (on_fullscreen_controls_enter_notify_event))
), (window), ((void*)0), (GConnectFlags) 0)
3045 window)g_signal_connect_data ((priv->fullscreen_controls), ("enter-notify-event"
), (((GCallback) (on_fullscreen_controls_enter_notify_event))
), (window), ((void*)0), (GConnectFlags) 0)
;
3046 g_signal_connect (priv->fullscreen_controls, "leave-notify-event",g_signal_connect_data ((priv->fullscreen_controls), ("leave-notify-event"
), (((GCallback) (on_fullscreen_controls_leave_notify_event))
), (window), ((void*)0), (GConnectFlags) 0)
3047 G_CALLBACK (on_fullscreen_controls_leave_notify_event),g_signal_connect_data ((priv->fullscreen_controls), ("leave-notify-event"
), (((GCallback) (on_fullscreen_controls_leave_notify_event))
), (window), ((void*)0), (GConnectFlags) 0)
3048 window)g_signal_connect_data ((priv->fullscreen_controls), ("leave-notify-event"
), (((GCallback) (on_fullscreen_controls_leave_notify_event))
), (window), ((void*)0), (GConnectFlags) 0)
;
3049}
3050
3051static void
3052can_search_again (PlumaDocument *doc,
3053 GParamSpec *pspec,
3054 PlumaWindow *window)
3055{
3056 gboolean sensitive;
3057 GtkAction *action;
3058
3059 if (doc != pluma_window_get_active_document (window))
3060 return;
3061
3062 sensitive = pluma_document_get_can_search_again (doc);
3063
3064 action = gtk_action_group_get_action (window->priv->action_group,
3065 "SearchFindNext");
3066 gtk_action_set_sensitive (action, sensitive);
3067
3068 action = gtk_action_group_get_action (window->priv->action_group,
3069 "SearchFindPrevious");
3070 gtk_action_set_sensitive (action, sensitive);
3071
3072 action = gtk_action_group_get_action (window->priv->action_group,
3073 "SearchClearHighlight");
3074 gtk_action_set_sensitive (action, sensitive);
3075}
3076
3077static void
3078can_undo (PlumaDocument *doc,
3079 GParamSpec *pspec,
3080 PlumaWindow *window)
3081{
3082 GtkAction *action;
3083 gboolean sensitive;
3084
3085 sensitive = gtk_source_buffer_can_undo (GTK_SOURCE_BUFFER (doc)((((GtkSourceBuffer*) (void *) ((doc))))));
3086
3087 if (doc != pluma_window_get_active_document (window))
3088 return;
3089
3090 action = gtk_action_group_get_action (window->priv->action_group,
3091 "EditUndo");
3092 gtk_action_set_sensitive (action, sensitive);
3093}
3094
3095static void
3096can_redo (PlumaDocument *doc,
3097 GParamSpec *pspec,
3098 PlumaWindow *window)
3099{
3100 GtkAction *action;
3101 gboolean sensitive;
3102
3103 sensitive = gtk_source_buffer_can_redo (GTK_SOURCE_BUFFER (doc)((((GtkSourceBuffer*) (void *) ((doc))))));
3104
3105 if (doc != pluma_window_get_active_document (window))
3106 return;
3107
3108 action = gtk_action_group_get_action (window->priv->action_group,
3109 "EditRedo");
3110 gtk_action_set_sensitive (action, sensitive);
3111}
3112
3113static void
3114selection_changed (PlumaDocument *doc,
3115 GParamSpec *pspec,
3116 PlumaWindow *window)
3117{
3118 PlumaTab *tab;
3119 PlumaView *view;
3120 GtkAction *action;
3121 PlumaTabState state;
3122 gboolean state_normal;
3123 gboolean editable;
3124
3125 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 3125, ((const char*) (__func__
))
);
3126
3127 if (doc != pluma_window_get_active_document (window))
3128 return;
3129
3130 tab = pluma_tab_get_from_document (doc);
3131 state = pluma_tab_get_state (tab);
3132 state_normal = (state == PLUMA_TAB_STATE_NORMAL);
3133
3134 view = pluma_tab_get_view (tab);
3135 editable = gtk_text_view_get_editable (GTK_TEXT_VIEW (view)((((GtkTextView*) (void *) ((view))))));
3136
3137 action = gtk_action_group_get_action (window->priv->action_group,
3138 "EditCut");
3139 gtk_action_set_sensitive (action,
3140 state_normal &&
3141 editable &&
3142 gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (doc)((((GtkTextBuffer*) (void *) ((doc)))))));
3143
3144 action = gtk_action_group_get_action (window->priv->action_group,
3145 "EditCopy");
3146 gtk_action_set_sensitive (action,
3147 (state_normal ||
3148 state == PLUMA_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION) &&
3149 gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (doc)((((GtkTextBuffer*) (void *) ((doc)))))));
3150
3151 action = gtk_action_group_get_action (window->priv->action_group,
3152 "EditDelete");
3153 gtk_action_set_sensitive (action,
3154 state_normal &&
3155 editable &&
3156 gtk_text_buffer_get_has_selection (GTK_TEXT_BUFFER (doc)((((GtkTextBuffer*) (void *) ((doc)))))));
3157
3158 peas_extension_set_call (window->priv->extensions, "update_state");
3159}
3160
3161static void
3162sync_languages_menu (PlumaDocument *doc,
3163 GParamSpec *pspec,
3164 PlumaWindow *window)
3165{
3166 update_languages_menu (window);
3167 peas_extension_set_call (window->priv->extensions, "update_state");
3168}
3169
3170static void
3171readonly_changed (PlumaDocument *doc,
3172 GParamSpec *pspec,
3173 PlumaWindow *window)
3174{
3175 set_sensitivity_according_to_tab (window, window->priv->active_tab);
3176
3177 sync_name (window->priv->active_tab, NULL((void*)0), window);
3178
3179 peas_extension_set_call (window->priv->extensions, "update_state");
3180}
3181
3182static void
3183editable_changed (PlumaView *view,
3184 GParamSpec *arg1,
3185 PlumaWindow *window)
3186{
3187 peas_extension_set_call (window->priv->extensions, "update_state");
3188}
3189
3190static void
3191update_sensitivity_according_to_open_tabs (PlumaWindow *window)
3192{
3193 GtkAction *action;
3194
3195 /* Set sensitivity */
3196 gtk_action_group_set_sensitive (window->priv->action_group,
3197 window->priv->num_tabs != 0);
3198
3199 action = gtk_action_group_get_action (window->priv->action_group,
3200 "DocumentsMoveToNewWindow");
3201 gtk_action_set_sensitive (action, window->priv->num_tabs > 1);
3202
3203 gtk_action_group_set_sensitive (window->priv->close_action_group,
3204 window->priv->num_tabs != 0);
3205}
3206
3207static void
3208notebook_tab_added (PlumaNotebook *notebook,
3209 PlumaTab *tab,
3210 PlumaWindow *window)
3211{
3212 PlumaView *view;
3213 PlumaDocument *doc;
3214
3215 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 3215, ((const char*) (__func__
))
);
3216
3217 g_return_if_fail ((window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION) == 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_76
; if ((window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION
) == 0) _g_boolean_var_76 = 1; else _g_boolean_var_76 = 0; _g_boolean_var_76
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION) == 0"
); return; } } while (0)
;
3218
3219 ++window->priv->num_tabs;
3220
3221 update_sensitivity_according_to_open_tabs (window);
3222
3223 view = pluma_tab_get_view (tab);
3224 doc = pluma_tab_get_document (tab);
3225
3226 /* IMPORTANT: remember to disconnect the signal in notebook_tab_removed
3227 * if a new signal is connected here */
3228
3229 g_signal_connect (tab,g_signal_connect_data ((tab), ("notify::name"), (((GCallback)
(sync_name))), (window), ((void*)0), (GConnectFlags) 0)
3230 "notify::name",g_signal_connect_data ((tab), ("notify::name"), (((GCallback)
(sync_name))), (window), ((void*)0), (GConnectFlags) 0)
3231 G_CALLBACK (sync_name),g_signal_connect_data ((tab), ("notify::name"), (((GCallback)
(sync_name))), (window), ((void*)0), (GConnectFlags) 0)
3232 window)g_signal_connect_data ((tab), ("notify::name"), (((GCallback)
(sync_name))), (window), ((void*)0), (GConnectFlags) 0)
;
3233 g_signal_connect (tab,g_signal_connect_data ((tab), ("notify::state"), (((GCallback
) (sync_state))), (window), ((void*)0), (GConnectFlags) 0)
3234 "notify::state",g_signal_connect_data ((tab), ("notify::state"), (((GCallback
) (sync_state))), (window), ((void*)0), (GConnectFlags) 0)
3235 G_CALLBACK (sync_state),g_signal_connect_data ((tab), ("notify::state"), (((GCallback
) (sync_state))), (window), ((void*)0), (GConnectFlags) 0)
3236 window)g_signal_connect_data ((tab), ("notify::state"), (((GCallback
) (sync_state))), (window), ((void*)0), (GConnectFlags) 0)
;
3237
3238 g_signal_connect (doc,g_signal_connect_data ((doc), ("cursor-moved"), (((GCallback)
(update_cursor_position_statusbar))), (window), ((void*)0), (
GConnectFlags) 0)
3239 "cursor-moved",g_signal_connect_data ((doc), ("cursor-moved"), (((GCallback)
(update_cursor_position_statusbar))), (window), ((void*)0), (
GConnectFlags) 0)
3240 G_CALLBACK (update_cursor_position_statusbar),g_signal_connect_data ((doc), ("cursor-moved"), (((GCallback)
(update_cursor_position_statusbar))), (window), ((void*)0), (
GConnectFlags) 0)
3241 window)g_signal_connect_data ((doc), ("cursor-moved"), (((GCallback)
(update_cursor_position_statusbar))), (window), ((void*)0), (
GConnectFlags) 0)
;
3242 g_signal_connect (doc,g_signal_connect_data ((doc), ("notify::can-search-again"), (
((GCallback) (can_search_again))), (window), ((void*)0), (GConnectFlags
) 0)
3243 "notify::can-search-again",g_signal_connect_data ((doc), ("notify::can-search-again"), (
((GCallback) (can_search_again))), (window), ((void*)0), (GConnectFlags
) 0)
3244 G_CALLBACK (can_search_again),g_signal_connect_data ((doc), ("notify::can-search-again"), (
((GCallback) (can_search_again))), (window), ((void*)0), (GConnectFlags
) 0)
3245 window)g_signal_connect_data ((doc), ("notify::can-search-again"), (
((GCallback) (can_search_again))), (window), ((void*)0), (GConnectFlags
) 0)
;
3246 g_signal_connect (doc,g_signal_connect_data ((doc), ("notify::can-undo"), (((GCallback
) (can_undo))), (window), ((void*)0), (GConnectFlags) 0)
3247 "notify::can-undo",g_signal_connect_data ((doc), ("notify::can-undo"), (((GCallback
) (can_undo))), (window), ((void*)0), (GConnectFlags) 0)
3248 G_CALLBACK (can_undo),g_signal_connect_data ((doc), ("notify::can-undo"), (((GCallback
) (can_undo))), (window), ((void*)0), (GConnectFlags) 0)
3249 window)g_signal_connect_data ((doc), ("notify::can-undo"), (((GCallback
) (can_undo))), (window), ((void*)0), (GConnectFlags) 0)
;
3250 g_signal_connect (doc,g_signal_connect_data ((doc), ("notify::can-redo"), (((GCallback
) (can_redo))), (window), ((void*)0), (GConnectFlags) 0)
3251 "notify::can-redo",g_signal_connect_data ((doc), ("notify::can-redo"), (((GCallback
) (can_redo))), (window), ((void*)0), (GConnectFlags) 0)
3252 G_CALLBACK (can_redo),g_signal_connect_data ((doc), ("notify::can-redo"), (((GCallback
) (can_redo))), (window), ((void*)0), (GConnectFlags) 0)
3253 window)g_signal_connect_data ((doc), ("notify::can-redo"), (((GCallback
) (can_redo))), (window), ((void*)0), (GConnectFlags) 0)
;
3254 g_signal_connect (doc,g_signal_connect_data ((doc), ("notify::has-selection"), (((GCallback
) (selection_changed))), (window), ((void*)0), (GConnectFlags
) 0)
3255 "notify::has-selection",g_signal_connect_data ((doc), ("notify::has-selection"), (((GCallback
) (selection_changed))), (window), ((void*)0), (GConnectFlags
) 0)
3256 G_CALLBACK (selection_changed),g_signal_connect_data ((doc), ("notify::has-selection"), (((GCallback
) (selection_changed))), (window), ((void*)0), (GConnectFlags
) 0)
3257 window)g_signal_connect_data ((doc), ("notify::has-selection"), (((GCallback
) (selection_changed))), (window), ((void*)0), (GConnectFlags
) 0)
;
3258 g_signal_connect (doc,g_signal_connect_data ((doc), ("notify::language"), (((GCallback
) (sync_languages_menu))), (window), ((void*)0), (GConnectFlags
) 0)
3259 "notify::language",g_signal_connect_data ((doc), ("notify::language"), (((GCallback
) (sync_languages_menu))), (window), ((void*)0), (GConnectFlags
) 0)
3260 G_CALLBACK (sync_languages_menu),g_signal_connect_data ((doc), ("notify::language"), (((GCallback
) (sync_languages_menu))), (window), ((void*)0), (GConnectFlags
) 0)
3261 window)g_signal_connect_data ((doc), ("notify::language"), (((GCallback
) (sync_languages_menu))), (window), ((void*)0), (GConnectFlags
) 0)
;
3262 g_signal_connect (doc,g_signal_connect_data ((doc), ("notify::read-only"), (((GCallback
) (readonly_changed))), (window), ((void*)0), (GConnectFlags)
0)
3263 "notify::read-only",g_signal_connect_data ((doc), ("notify::read-only"), (((GCallback
) (readonly_changed))), (window), ((void*)0), (GConnectFlags)
0)
3264 G_CALLBACK (readonly_changed),g_signal_connect_data ((doc), ("notify::read-only"), (((GCallback
) (readonly_changed))), (window), ((void*)0), (GConnectFlags)
0)
3265 window)g_signal_connect_data ((doc), ("notify::read-only"), (((GCallback
) (readonly_changed))), (window), ((void*)0), (GConnectFlags)
0)
;
3266 g_signal_connect (view,g_signal_connect_data ((view), ("toggle_overwrite"), (((GCallback
) (update_overwrite_mode_statusbar))), (window), ((void*)0), (
GConnectFlags) 0)
3267 "toggle_overwrite",g_signal_connect_data ((view), ("toggle_overwrite"), (((GCallback
) (update_overwrite_mode_statusbar))), (window), ((void*)0), (
GConnectFlags) 0)
3268 G_CALLBACK (update_overwrite_mode_statusbar),g_signal_connect_data ((view), ("toggle_overwrite"), (((GCallback
) (update_overwrite_mode_statusbar))), (window), ((void*)0), (
GConnectFlags) 0)
3269 window)g_signal_connect_data ((view), ("toggle_overwrite"), (((GCallback
) (update_overwrite_mode_statusbar))), (window), ((void*)0), (
GConnectFlags) 0)
;
3270 g_signal_connect (view,g_signal_connect_data ((view), ("notify::editable"), (((GCallback
) (editable_changed))), (window), ((void*)0), (GConnectFlags)
0)
3271 "notify::editable",g_signal_connect_data ((view), ("notify::editable"), (((GCallback
) (editable_changed))), (window), ((void*)0), (GConnectFlags)
0)
3272 G_CALLBACK (editable_changed),g_signal_connect_data ((view), ("notify::editable"), (((GCallback
) (editable_changed))), (window), ((void*)0), (GConnectFlags)
0)
3273 window)g_signal_connect_data ((view), ("notify::editable"), (((GCallback
) (editable_changed))), (window), ((void*)0), (GConnectFlags)
0)
;
3274
3275 update_documents_list_menu (window);
3276
3277 g_signal_connect (view,g_signal_connect_data ((view), ("drop_uris"), (((GCallback) (
drop_uris_cb))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
3278 "drop_uris",g_signal_connect_data ((view), ("drop_uris"), (((GCallback) (
drop_uris_cb))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
3279 G_CALLBACK (drop_uris_cb),g_signal_connect_data ((view), ("drop_uris"), (((GCallback) (
drop_uris_cb))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
3280 NULL)g_signal_connect_data ((view), ("drop_uris"), (((GCallback) (
drop_uris_cb))), (((void*)0)), ((void*)0), (GConnectFlags) 0)
;
3281
3282 update_window_state (window);
3283
3284 g_signal_emit (G_OBJECT (window)((((GObject*) (void *) ((window))))), signals[TAB_ADDED], 0, tab);
3285}
3286
3287static void
3288notebook_tab_removed (PlumaNotebook *notebook,
3289 PlumaTab *tab,
3290 PlumaWindow *window)
3291{
3292 PlumaView *view;
3293 PlumaDocument *doc;
3294
3295 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 3295, ((const char*) (__func__
))
);
3296
3297 g_return_if_fail ((window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION) == 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_77
; if ((window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION
) == 0) _g_boolean_var_77 = 1; else _g_boolean_var_77 = 0; _g_boolean_var_77
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION) == 0"
); return; } } while (0)
;
3298
3299 --window->priv->num_tabs;
3300
3301 view = pluma_tab_get_view (tab);
3302 doc = pluma_tab_get_document (tab);
3303
3304 g_signal_handlers_disconnect_by_func (tab,g_signal_handlers_disconnect_matched ((tab), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (sync_name))), (window))
3305 G_CALLBACK (sync_name),g_signal_handlers_disconnect_matched ((tab), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (sync_name))), (window))
3306 window)g_signal_handlers_disconnect_matched ((tab), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (sync_name))), (window))
;
3307 g_signal_handlers_disconnect_by_func (tab,g_signal_handlers_disconnect_matched ((tab), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (sync_state))), (window))
3308 G_CALLBACK (sync_state),g_signal_handlers_disconnect_matched ((tab), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (sync_state))), (window))
3309 window)g_signal_handlers_disconnect_matched ((tab), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (sync_state))), (window))
;
3310 g_signal_handlers_disconnect_by_func (doc,g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (update_cursor_position_statusbar))), (window
))
3311 G_CALLBACK (update_cursor_position_statusbar),g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (update_cursor_position_statusbar))), (window
))
3312 window)g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (update_cursor_position_statusbar))), (window
))
;
3313 g_signal_handlers_disconnect_by_func (doc,g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (can_search_again))), (window))
3314 G_CALLBACK (can_search_again),g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (can_search_again))), (window))
3315 window)g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (can_search_again))), (window))
;
3316 g_signal_handlers_disconnect_by_func (doc,g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (can_undo))), (window))
3317 G_CALLBACK (can_undo),g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (can_undo))), (window))
3318 window)g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (can_undo))), (window))
;
3319 g_signal_handlers_disconnect_by_func (doc,g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (can_redo))), (window))
3320 G_CALLBACK (can_redo),g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (can_redo))), (window))
3321 window)g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (can_redo))), (window))
;
3322 g_signal_handlers_disconnect_by_func (doc,g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (selection_changed))), (window))
3323 G_CALLBACK (selection_changed),g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (selection_changed))), (window))
3324 window)g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (selection_changed))), (window))
;
3325 g_signal_handlers_disconnect_by_func (doc,g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (sync_languages_menu))), (window))
3326 G_CALLBACK (sync_languages_menu),g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (sync_languages_menu))), (window))
3327 window)g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (sync_languages_menu))), (window))
;
3328 g_signal_handlers_disconnect_by_func (doc,g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (readonly_changed))), (window))
3329 G_CALLBACK (readonly_changed),g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (readonly_changed))), (window))
3330 window)g_signal_handlers_disconnect_matched ((doc), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (readonly_changed))), (window))
;
3331 g_signal_handlers_disconnect_by_func (view,g_signal_handlers_disconnect_matched ((view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (update_overwrite_mode_statusbar))), (window
))
3332 G_CALLBACK (update_overwrite_mode_statusbar),g_signal_handlers_disconnect_matched ((view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (update_overwrite_mode_statusbar))), (window
))
3333 window)g_signal_handlers_disconnect_matched ((view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (update_overwrite_mode_statusbar))), (window
))
;
3334 g_signal_handlers_disconnect_by_func (view,g_signal_handlers_disconnect_matched ((view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (editable_changed))), (window))
3335 G_CALLBACK (editable_changed),g_signal_handlers_disconnect_matched ((view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (editable_changed))), (window))
3336 window)g_signal_handlers_disconnect_matched ((view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (editable_changed))), (window))
;
3337 g_signal_handlers_disconnect_by_func (view,g_signal_handlers_disconnect_matched ((view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (drop_uris_cb))), (((void*)0)))
3338 G_CALLBACK (drop_uris_cb),g_signal_handlers_disconnect_matched ((view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (drop_uris_cb))), (((void*)0)))
3339 NULL)g_signal_handlers_disconnect_matched ((view), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (drop_uris_cb))), (((void*)0)))
;
3340
3341#if GLIB_CHECK_VERSION(2,62,0)(2 > (2) || (2 == (2) && 76 > (62)) || (2 == (2
) && 76 == (62) && 5 >= (0)))
3342 if (tab == pluma_window_get_active_tab (window))
3343 {
3344 g_clear_signal_handler (&window->priv->tab_width_id, view)do { gpointer const _instance = (view); gulong *const _handler_id_ptr
= (&window->priv->tab_width_id); const gulong _handler_id
= *_handler_id_ptr; if (_handler_id > 0) { *_handler_id_ptr
= 0; g_signal_handler_disconnect (_instance, _handler_id); }
} while (0)
;
3345 g_clear_signal_handler (&window->priv->spaces_instead_of_tabs_id, view)do { gpointer const _instance = (view); gulong *const _handler_id_ptr
= (&window->priv->spaces_instead_of_tabs_id); const
gulong _handler_id = *_handler_id_ptr; if (_handler_id > 0
) { *_handler_id_ptr = 0; g_signal_handler_disconnect (_instance
, _handler_id); } } while (0)
;
3346 g_clear_signal_handler (&window->priv->language_changed_id, doc)do { gpointer const _instance = (doc); gulong *const _handler_id_ptr
= (&window->priv->language_changed_id); const gulong
_handler_id = *_handler_id_ptr; if (_handler_id > 0) { *_handler_id_ptr
= 0; g_signal_handler_disconnect (_instance, _handler_id); }
} while (0)
;
3347 }
3348#else
3349 if (window->priv->tab_width_id && tab == pluma_window_get_active_tab (window))
3350 {
3351 g_signal_handler_disconnect (view, window->priv->tab_width_id);
3352 window->priv->tab_width_id = 0;
3353 }
3354
3355 if (window->priv->spaces_instead_of_tabs_id && tab == pluma_window_get_active_tab (window))
3356 {
3357 g_signal_handler_disconnect (view, window->priv->spaces_instead_of_tabs_id);
3358 window->priv->spaces_instead_of_tabs_id = 0;
3359 }
3360
3361 if (window->priv->language_changed_id && tab == pluma_window_get_active_tab (window))
3362 {
3363 g_signal_handler_disconnect (doc, window->priv->language_changed_id);
3364 window->priv->language_changed_id = 0;
3365 }
3366#endif
3367
3368 g_return_if_fail (window->priv->num_tabs >= 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_78
; if (window->priv->num_tabs >= 0) _g_boolean_var_78
= 1; else _g_boolean_var_78 = 0; _g_boolean_var_78; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "window->priv->num_tabs >= 0"); return
; } } while (0)
;
3369 if (window->priv->num_tabs == 0)
3370 {
3371 window->priv->active_tab = NULL((void*)0);
3372
3373 set_title (window);
3374
3375 /* Remove line and col info */
3376 pluma_statusbar_set_cursor_position (PLUMA_STATUSBAR (window->priv->statusbar)((((PlumaStatusbar*) (void *) ((window->priv->statusbar
)))))
,
3377 -1,
3378 -1);
3379
3380 pluma_statusbar_clear_overwrite (PLUMA_STATUSBAR (window->priv->statusbar)((((PlumaStatusbar*) (void *) ((window->priv->statusbar
)))))
);
3381
3382 /* hide the combos */
3383 gtk_widget_hide (window->priv->tab_width_combo);
3384 gtk_widget_hide (window->priv->language_combo);
3385 }
3386
3387 if (!window->priv->removing_tabs)
3388 {
3389 update_documents_list_menu (window);
3390 update_next_prev_doc_sensitivity_per_window (window);
3391 }
3392 else
3393 {
3394 if (window->priv->num_tabs == 0)
3395 {
3396 update_documents_list_menu (window);
3397 update_next_prev_doc_sensitivity_per_window (window);
3398 }
3399 }
3400
3401 update_sensitivity_according_to_open_tabs (window);
3402
3403 if (window->priv->num_tabs == 0)
3404 {
3405 peas_extension_set_call (window->priv->extensions, "update_state");
3406 }
3407
3408 update_window_state (window);
3409
3410 g_signal_emit (G_OBJECT (window)((((GObject*) (void *) ((window))))), signals[TAB_REMOVED], 0, tab);
3411}
3412
3413static void
3414notebook_tabs_reordered (PlumaNotebook *notebook,
3415 PlumaWindow *window)
3416{
3417 update_documents_list_menu (window);
3418 update_next_prev_doc_sensitivity_per_window (window);
3419
3420 g_signal_emit (G_OBJECT (window)((((GObject*) (void *) ((window))))), signals[TABS_REORDERED], 0);
3421}
3422
3423static void
3424notebook_tab_detached (PlumaNotebook *notebook,
3425 PlumaTab *tab,
3426 PlumaWindow *window)
3427{
3428 PlumaWindow *new_window;
3429
3430 new_window = clone_window (window);
3431
3432 pluma_notebook_move_tab (notebook,
3433 PLUMA_NOTEBOOK (_pluma_window_get_notebook (new_window))((((PlumaNotebook*) (void *) ((_pluma_window_get_notebook (new_window
))))))
,
3434 tab, 0);
3435
3436 gtk_window_set_position (GTK_WINDOW (new_window)((((GtkWindow*) (void *) ((new_window))))), GTK_WIN_POS_MOUSE);
3437
3438 gtk_widget_show (GTK_WIDGET (new_window)((((GtkWidget*) (void *) ((new_window))))));
3439}
3440
3441static void
3442notebook_tab_close_request (PlumaNotebook *notebook,
3443 PlumaTab *tab,
3444 GtkWindow *window)
3445{
3446 /* Note: we are destroying the tab before the default handler
3447 * seems to be ok, but we need to keep an eye on this. */
3448 _pluma_cmd_file_close_tab (tab, PLUMA_WINDOW (window)((((PlumaWindow*) (void *) ((window))))));
3449}
3450
3451static gboolean
3452show_notebook_popup_menu (GtkNotebook *notebook,
3453 PlumaWindow *window,
3454 GdkEventButton *event)
3455{
3456 GtkWidget *menu;
3457// GtkAction *action;
3458
3459 menu = gtk_ui_manager_get_widget (window->priv->manager, "/NotebookPopup");
3460 g_return_val_if_fail (menu != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_79
; if (menu != ((void*)0)) _g_boolean_var_79 = 1; else _g_boolean_var_79
= 0; _g_boolean_var_79; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "menu != NULL"); return
((0)); } } while (0)
;
3461
3462// CHECK do we need this?
3463#if 0
3464 /* allow extensions to sync when showing the popup */
3465 action = gtk_action_group_get_action (window->priv->action_group,
3466 "NotebookPopupAction");
3467 g_return_val_if_fail (action != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_80
; if (action != ((void*)0)) _g_boolean_var_80 = 1; else _g_boolean_var_80
= 0; _g_boolean_var_80; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "action != NULL")
; return ((0)); } } while (0)
;
3468 gtk_action_activate (action);
3469#endif
3470
3471 GtkWidget *tab;
3472 GtkWidget *tab_label;
3473
3474 tab = GTK_WIDGET (pluma_window_get_active_tab (window))((((GtkWidget*) (void *) ((pluma_window_get_active_tab (window
))))))
;
3475 g_return_val_if_fail (tab != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_81
; if (tab != ((void*)0)) _g_boolean_var_81 = 1; else _g_boolean_var_81
= 0; _g_boolean_var_81; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "tab != NULL"); return
((0)); } } while (0)
;
3476
3477 tab_label = gtk_notebook_get_tab_label (notebook, tab);
3478
3479 gtk_menu_popup_at_widget (GTK_MENU (menu)((((GtkMenu*) (void *) ((menu))))),
3480 tab_label,
3481 GDK_GRAVITY_SOUTH_WEST,
3482 GDK_GRAVITY_NORTH_WEST,
3483 (const GdkEvent*) event);
3484
3485 gtk_menu_shell_select_first (GTK_MENU_SHELL (menu)((((GtkMenuShell*) (void *) ((menu))))), FALSE(0));
3486
3487 return TRUE(!(0));
3488}
3489
3490static gboolean
3491notebook_button_press_event (GtkNotebook *notebook,
3492 GdkEventButton *event,
3493 PlumaWindow *window)
3494{
3495 if (event->type == GDK_BUTTON_PRESS)
3496 {
3497 if (event->button == 3)
3498 return show_notebook_popup_menu (notebook, window, event);
3499
3500 else if (event->button == 2)
3501 {
3502 PlumaTab *tab;
3503 tab = pluma_window_get_active_tab (window);
3504 notebook_tab_close_request (PLUMA_NOTEBOOK (notebook)((((PlumaNotebook*) (void *) ((notebook))))), tab, GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
3505 }
3506 }
3507 else if ((event->type == GDK_2BUTTON_PRESS) && (event->button == 1))
3508 {
3509 pluma_window_create_tab (window, TRUE(!(0)));
3510 }
3511
3512 return FALSE(0);
3513}
3514
3515static gboolean
3516notebook_scroll_event (GtkNotebook *notebook,
3517 GdkEventScroll *event,
3518 PlumaWindow *window)
3519{
3520 if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_LEFT)
3521 {
3522 gtk_notebook_prev_page (notebook);
3523 }
3524 else if (event->direction == GDK_SCROLL_DOWN || event->direction == GDK_SCROLL_RIGHT)
3525 {
3526 gtk_notebook_next_page (notebook);
3527 }
3528
3529 return FALSE(0);
3530}
3531
3532static gboolean
3533notebook_popup_menu (GtkNotebook *notebook,
3534 PlumaWindow *window)
3535{
3536 /* Only respond if the notebook is the actual focus */
3537 if (PLUMA_IS_NOTEBOOK (gtk_window_get_focus (GTK_WINDOW (window)))(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(gtk_window_get_focus (((((GtkWindow*) (void *) ((window)))))
))); GType __t = ((pluma_notebook_get_type ())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
)
3538 {
3539 return show_notebook_popup_menu (notebook, window, NULL((void*)0));
3540 }
3541
3542 return FALSE(0);
3543}
3544
3545static void
3546side_panel_size_allocate (GtkWidget *widget,
3547 GtkAllocation *allocation,
3548 PlumaWindow *window)
3549{
3550 window->priv->side_panel_size = allocation->width;
3551}
3552
3553static void
3554bottom_panel_size_allocate (GtkWidget *widget,
3555 GtkAllocation *allocation,
3556 PlumaWindow *window)
3557{
3558 window->priv->bottom_panel_size = allocation->height;
3559}
3560
3561static void
3562hpaned_restore_position (GtkWidget *widget,
3563 PlumaWindow *window)
3564{
3565 gint pos;
3566
3567 pluma_debug_message (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 3567, ((const char*) (__func__
))
,
3568 "Restoring hpaned position: side panel size %d",
3569 window->priv->side_panel_size);
3570
3571 pos = MAX (100, window->priv->side_panel_size)(((100) > (window->priv->side_panel_size)) ? (100) :
(window->priv->side_panel_size))
;
3572 gtk_paned_set_position (GTK_PANED (window->priv->hpaned)((((GtkPaned*) (void *) ((window->priv->hpaned))))), pos);
3573
3574 /* start monitoring the size */
3575 g_signal_connect (window->priv->side_panel,g_signal_connect_data ((window->priv->side_panel), ("size-allocate"
), (((GCallback) (side_panel_size_allocate))), (window), ((void
*)0), (GConnectFlags) 0)
3576 "size-allocate",g_signal_connect_data ((window->priv->side_panel), ("size-allocate"
), (((GCallback) (side_panel_size_allocate))), (window), ((void
*)0), (GConnectFlags) 0)
3577 G_CALLBACK (side_panel_size_allocate),g_signal_connect_data ((window->priv->side_panel), ("size-allocate"
), (((GCallback) (side_panel_size_allocate))), (window), ((void
*)0), (GConnectFlags) 0)
3578 window)g_signal_connect_data ((window->priv->side_panel), ("size-allocate"
), (((GCallback) (side_panel_size_allocate))), (window), ((void
*)0), (GConnectFlags) 0)
;
3579
3580 /* run this only once */
3581 g_signal_handlers_disconnect_by_func (widget, hpaned_restore_position, window)g_signal_handlers_disconnect_matched ((widget), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (hpaned_restore_position), (window))
;
3582}
3583
3584static void
3585vpaned_restore_position (GtkWidget *widget,
3586 PlumaWindow *window)
3587{
3588 GtkAllocation allocation;
3589 gint pos;
3590
3591 gtk_widget_get_allocation (widget, &allocation);
3592
3593 pluma_debug_message (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 3593, ((const char*) (__func__
))
,
3594 "Restoring vpaned position: bottom panel size %d",
3595 window->priv->bottom_panel_size);
3596
3597 pos = allocation.height - MAX (50, window->priv->bottom_panel_size)(((50) > (window->priv->bottom_panel_size)) ? (50) :
(window->priv->bottom_panel_size))
;
3598 gtk_paned_set_position (GTK_PANED (window->priv->vpaned)((((GtkPaned*) (void *) ((window->priv->vpaned))))), pos);
3599
3600 /* start monitoring the size */
3601 g_signal_connect (window->priv->bottom_panel,g_signal_connect_data ((window->priv->bottom_panel), ("size-allocate"
), (((GCallback) (bottom_panel_size_allocate))), (window), ((
void*)0), (GConnectFlags) 0)
3602 "size-allocate",g_signal_connect_data ((window->priv->bottom_panel), ("size-allocate"
), (((GCallback) (bottom_panel_size_allocate))), (window), ((
void*)0), (GConnectFlags) 0)
3603 G_CALLBACK (bottom_panel_size_allocate),g_signal_connect_data ((window->priv->bottom_panel), ("size-allocate"
), (((GCallback) (bottom_panel_size_allocate))), (window), ((
void*)0), (GConnectFlags) 0)
3604 window)g_signal_connect_data ((window->priv->bottom_panel), ("size-allocate"
), (((GCallback) (bottom_panel_size_allocate))), (window), ((
void*)0), (GConnectFlags) 0)
;
3605
3606 /* run this only once */
3607 g_signal_handlers_disconnect_by_func (widget, vpaned_restore_position, window)g_signal_handlers_disconnect_matched ((widget), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (vpaned_restore_position), (window))
;
3608}
3609
3610static void
3611side_panel_visibility_changed (GtkWidget *side_panel,
3612 PlumaWindow *window)
3613{
3614 gboolean visible;
3615 GtkAction *action;
3616
3617 visible = gtk_widget_get_visible (side_panel);
3618
3619 if (!g_settings_get_boolean (window->priv->editor_settings, "show-tabs-with-side-pane"))
3620 {
3621 if (visible)
3622 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (window->priv->notebook)((((GtkNotebook*) (void *) ((window->priv->notebook))))
)
, FALSE(0));
3623 else
3624 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (window->priv->notebook)((((GtkNotebook*) (void *) ((window->priv->notebook))))
)
,
3625 g_settings_get_boolean (window->priv->editor_settings, "show-single-tab") ||
3626 (gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->priv->notebook)((((GtkNotebook*) (void *) ((window->priv->notebook))))
)
) > 1));
3627 }
3628 else
3629 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (window->priv->notebook)((((GtkNotebook*) (void *) ((window->priv->notebook))))
)
,
3630 g_settings_get_boolean (window->priv->editor_settings, "show-single-tab") ||
3631 (gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->priv->notebook)((((GtkNotebook*) (void *) ((window->priv->notebook))))
)
) > 1));
3632
3633 g_settings_set_boolean (window->priv->editor_settings,
3634 PLUMA_SETTINGS_SIDE_PANE_VISIBLE"side-pane-visible",
3635 visible);
3636
3637 action = gtk_action_group_get_action (window->priv->panes_action_group,
3638 "ViewSidePane");
3639
3640 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action)))))) != visible)
3641 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action))))), visible);
3642
3643 /* focus the document */
3644 if (!visible && window->priv->active_tab != NULL((void*)0))
3645 gtk_widget_grab_focus (GTK_WIDGET (pluma_tab_get_view (PLUMA_TAB (window->priv->active_tab)))((((GtkWidget*) (void *) ((pluma_tab_get_view (((((PlumaTab*)
(void *) ((window->priv->active_tab)))))))))))
);
3646}
3647
3648static void
3649create_side_panel (PlumaWindow *window)
3650{
3651 GtkWidget *documents_panel;
3652
3653 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 3653, ((const char*) (__func__
))
);
3654
3655 window->priv->side_panel = pluma_panel_new (GTK_ORIENTATION_VERTICAL);
3656
3657 gtk_paned_pack1 (GTK_PANED (window->priv->hpaned)((((GtkPaned*) (void *) ((window->priv->hpaned))))),
3658 window->priv->side_panel,
3659 FALSE(0),
3660 FALSE(0));
3661
3662 g_signal_connect_after (window->priv->side_panel,g_signal_connect_data ((window->priv->side_panel), ("show"
), (((GCallback) (side_panel_visibility_changed))), (window),
((void*)0), G_CONNECT_AFTER)
3663 "show",g_signal_connect_data ((window->priv->side_panel), ("show"
), (((GCallback) (side_panel_visibility_changed))), (window),
((void*)0), G_CONNECT_AFTER)
3664 G_CALLBACK (side_panel_visibility_changed),g_signal_connect_data ((window->priv->side_panel), ("show"
), (((GCallback) (side_panel_visibility_changed))), (window),
((void*)0), G_CONNECT_AFTER)
3665 window)g_signal_connect_data ((window->priv->side_panel), ("show"
), (((GCallback) (side_panel_visibility_changed))), (window),
((void*)0), G_CONNECT_AFTER)
;
3666 g_signal_connect_after (window->priv->side_panel,g_signal_connect_data ((window->priv->side_panel), ("hide"
), (((GCallback) (side_panel_visibility_changed))), (window),
((void*)0), G_CONNECT_AFTER)
3667 "hide",g_signal_connect_data ((window->priv->side_panel), ("hide"
), (((GCallback) (side_panel_visibility_changed))), (window),
((void*)0), G_CONNECT_AFTER)
3668 G_CALLBACK (side_panel_visibility_changed),g_signal_connect_data ((window->priv->side_panel), ("hide"
), (((GCallback) (side_panel_visibility_changed))), (window),
((void*)0), G_CONNECT_AFTER)
3669 window)g_signal_connect_data ((window->priv->side_panel), ("hide"
), (((GCallback) (side_panel_visibility_changed))), (window),
((void*)0), G_CONNECT_AFTER)
;
3670
3671 documents_panel = pluma_documents_panel_new (window);
3672 pluma_panel_add_item_with_icon (PLUMA_PANEL (window->priv->side_panel)((((PlumaPanel*) (void *) ((window->priv->side_panel)))
))
,
3673 documents_panel,
3674 _("Documents")dcgettext (((void*)0), "Documents", 5),
3675 "text-x-generic");
3676}
3677
3678static void
3679bottom_panel_visibility_changed (PlumaPanel *bottom_panel,
3680 PlumaWindow *window)
3681{
3682 gboolean visible;
3683 GtkAction *action;
3684
3685 visible = gtk_widget_get_visible (GTK_WIDGET (bottom_panel)((((GtkWidget*) (void *) ((bottom_panel))))));
3686
3687 g_settings_set_boolean (window->priv->editor_settings,
3688 PLUMA_SETTINGS_BOTTOM_PANE_VISIBLE"bottom-panel-visible",
3689 visible);
3690
3691 action = gtk_action_group_get_action (window->priv->panes_action_group,
3692 "ViewBottomPane");
3693
3694 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action)))))) != visible)
3695 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action))))), visible);
3696
3697 /* focus the document */
3698 if (!visible && window->priv->active_tab != NULL((void*)0))
3699 gtk_widget_grab_focus (GTK_WIDGET (pluma_tab_get_view (PLUMA_TAB (window->priv->active_tab)))((((GtkWidget*) (void *) ((pluma_tab_get_view (((((PlumaTab*)
(void *) ((window->priv->active_tab)))))))))))
);
3700}
3701
3702static void
3703bottom_panel_item_removed (PlumaPanel *panel,
3704 GtkWidget *item,
3705 PlumaWindow *window)
3706{
3707 if (pluma_panel_get_n_items (panel) == 0)
3708 {
3709 GtkAction *action;
3710
3711 gtk_widget_hide (GTK_WIDGET (panel)((((GtkWidget*) (void *) ((panel))))));
3712
3713 action = gtk_action_group_get_action (window->priv->panes_action_group,
3714 "ViewBottomPane");
3715 gtk_action_set_sensitive (action, FALSE(0));
3716 }
3717}
3718
3719static void
3720bottom_panel_item_added (PlumaPanel *panel,
3721 GtkWidget *item,
3722 PlumaWindow *window)
3723{
3724 /* if it's the first item added, set the menu item
3725 * sensitive and if needed show the panel */
3726 if (pluma_panel_get_n_items (panel) == 1)
3727 {
3728 GtkAction *action;
3729 gboolean show;
3730
3731 action = gtk_action_group_get_action (window->priv->panes_action_group,
3732 "ViewBottomPane");
3733 gtk_action_set_sensitive (action, TRUE(!(0)));
3734
3735 show = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action))))));
3736 if (show)
3737 gtk_widget_show (GTK_WIDGET (panel)((((GtkWidget*) (void *) ((panel))))));
3738 }
3739}
3740
3741static void
3742create_bottom_panel (PlumaWindow *window)
3743{
3744 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 3744, ((const char*) (__func__
))
);
3745
3746 window->priv->bottom_panel = pluma_panel_new (GTK_ORIENTATION_HORIZONTAL);
3747
3748 gtk_paned_pack2 (GTK_PANED (window->priv->vpaned)((((GtkPaned*) (void *) ((window->priv->vpaned))))),
3749 window->priv->bottom_panel,
3750 FALSE(0),
3751 FALSE(0));
3752
3753 g_signal_connect_after (window->priv->bottom_panel,g_signal_connect_data ((window->priv->bottom_panel), ("show"
), (((GCallback) (bottom_panel_visibility_changed))), (window
), ((void*)0), G_CONNECT_AFTER)
3754 "show",g_signal_connect_data ((window->priv->bottom_panel), ("show"
), (((GCallback) (bottom_panel_visibility_changed))), (window
), ((void*)0), G_CONNECT_AFTER)
3755 G_CALLBACK (bottom_panel_visibility_changed),g_signal_connect_data ((window->priv->bottom_panel), ("show"
), (((GCallback) (bottom_panel_visibility_changed))), (window
), ((void*)0), G_CONNECT_AFTER)
3756 window)g_signal_connect_data ((window->priv->bottom_panel), ("show"
), (((GCallback) (bottom_panel_visibility_changed))), (window
), ((void*)0), G_CONNECT_AFTER)
;
3757 g_signal_connect_after (window->priv->bottom_panel,g_signal_connect_data ((window->priv->bottom_panel), ("hide"
), (((GCallback) (bottom_panel_visibility_changed))), (window
), ((void*)0), G_CONNECT_AFTER)
3758 "hide",g_signal_connect_data ((window->priv->bottom_panel), ("hide"
), (((GCallback) (bottom_panel_visibility_changed))), (window
), ((void*)0), G_CONNECT_AFTER)
3759 G_CALLBACK (bottom_panel_visibility_changed),g_signal_connect_data ((window->priv->bottom_panel), ("hide"
), (((GCallback) (bottom_panel_visibility_changed))), (window
), ((void*)0), G_CONNECT_AFTER)
3760 window)g_signal_connect_data ((window->priv->bottom_panel), ("hide"
), (((GCallback) (bottom_panel_visibility_changed))), (window
), ((void*)0), G_CONNECT_AFTER)
;
3761}
3762
3763static void
3764init_panels_visibility (PlumaWindow *window)
3765{
3766 gint active_page;
3767 gboolean side_pane_visible;
3768 gboolean bottom_pane_visible;
3769
3770 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 3770, ((const char*) (__func__
))
);
3771
3772 /* side pane */
3773 active_page = g_settings_get_int (window->priv->editor_settings,
3774 PLUMA_SETTINGS_SIDE_PANEL_ACTIVE_PAGE"side-panel-active-page");
3775 _pluma_panel_set_active_item_by_id (PLUMA_PANEL (window->priv->side_panel)((((PlumaPanel*) (void *) ((window->priv->side_panel)))
))
,
3776 active_page);
3777
3778 side_pane_visible = g_settings_get_boolean (window->priv->editor_settings,
3779 PLUMA_SETTINGS_SIDE_PANE_VISIBLE"side-pane-visible");
3780 bottom_pane_visible = g_settings_get_boolean (window->priv->editor_settings,
3781 PLUMA_SETTINGS_BOTTOM_PANE_VISIBLE"bottom-panel-visible");
3782
3783 if (side_pane_visible)
3784
3785 {
3786 gtk_widget_show (window->priv->side_panel);
3787 }
3788
3789 /* bottom pane, it can be empty */
3790 if (pluma_panel_get_n_items (PLUMA_PANEL (window->priv->bottom_panel)((((PlumaPanel*) (void *) ((window->priv->bottom_panel)
))))
) > 0)
3791 {
3792 active_page = g_settings_get_int (window->priv->editor_settings,
3793 PLUMA_SETTINGS_BOTTOM_PANEL_ACTIVE_PAGE"bottom-panel-active-page");
3794 _pluma_panel_set_active_item_by_id (PLUMA_PANEL (window->priv->bottom_panel)((((PlumaPanel*) (void *) ((window->priv->bottom_panel)
))))
,
3795 active_page);
3796
3797 if (bottom_pane_visible)
3798 {
3799 gtk_widget_show (window->priv->bottom_panel);
3800 }
3801 }
3802 else
3803 {
3804 GtkAction *action;
3805 action = gtk_action_group_get_action (window->priv->panes_action_group,
3806 "ViewBottomPane");
3807 gtk_action_set_sensitive (action, FALSE(0));
3808 }
3809
3810 /* start track sensitivity after the initial state is set */
3811 window->priv->bottom_panel_item_removed_handler_id =
3812 g_signal_connect (window->priv->bottom_panel,g_signal_connect_data ((window->priv->bottom_panel), ("item_removed"
), (((GCallback) (bottom_panel_item_removed))), (window), ((void
*)0), (GConnectFlags) 0)
3813 "item_removed",g_signal_connect_data ((window->priv->bottom_panel), ("item_removed"
), (((GCallback) (bottom_panel_item_removed))), (window), ((void
*)0), (GConnectFlags) 0)
3814 G_CALLBACK (bottom_panel_item_removed),g_signal_connect_data ((window->priv->bottom_panel), ("item_removed"
), (((GCallback) (bottom_panel_item_removed))), (window), ((void
*)0), (GConnectFlags) 0)
3815 window)g_signal_connect_data ((window->priv->bottom_panel), ("item_removed"
), (((GCallback) (bottom_panel_item_removed))), (window), ((void
*)0), (GConnectFlags) 0)
;
3816
3817 g_signal_connect (window->priv->bottom_panel,g_signal_connect_data ((window->priv->bottom_panel), ("item_added"
), (((GCallback) (bottom_panel_item_added))), (window), ((void
*)0), (GConnectFlags) 0)
3818 "item_added",g_signal_connect_data ((window->priv->bottom_panel), ("item_added"
), (((GCallback) (bottom_panel_item_added))), (window), ((void
*)0), (GConnectFlags) 0)
3819 G_CALLBACK (bottom_panel_item_added),g_signal_connect_data ((window->priv->bottom_panel), ("item_added"
), (((GCallback) (bottom_panel_item_added))), (window), ((void
*)0), (GConnectFlags) 0)
3820 window)g_signal_connect_data ((window->priv->bottom_panel), ("item_added"
), (((GCallback) (bottom_panel_item_added))), (window), ((void
*)0), (GConnectFlags) 0)
;
3821}
3822
3823static void
3824clipboard_owner_change (GtkClipboard *clipboard,
3825 GdkEventOwnerChange *event,
3826 PlumaWindow *window)
3827{
3828 set_paste_sensitivity_according_to_clipboard (window, clipboard);
3829}
3830
3831static void
3832window_realized (GtkWidget *window,
3833 gpointer *data)
3834{
3835 GtkClipboard *clipboard;
3836
3837 clipboard = gtk_widget_get_clipboard (window, GDK_SELECTION_CLIPBOARD((GdkAtom)((gpointer) (gulong) (69))));
3838
3839 g_signal_connect (clipboard,g_signal_connect_data ((clipboard), ("owner_change"), (((GCallback
) (clipboard_owner_change))), (window), ((void*)0), (GConnectFlags
) 0)
3840 "owner_change",g_signal_connect_data ((clipboard), ("owner_change"), (((GCallback
) (clipboard_owner_change))), (window), ((void*)0), (GConnectFlags
) 0)
3841 G_CALLBACK (clipboard_owner_change),g_signal_connect_data ((clipboard), ("owner_change"), (((GCallback
) (clipboard_owner_change))), (window), ((void*)0), (GConnectFlags
) 0)
3842 window)g_signal_connect_data ((clipboard), ("owner_change"), (((GCallback
) (clipboard_owner_change))), (window), ((void*)0), (GConnectFlags
) 0)
;
3843}
3844
3845static void
3846window_unrealized (GtkWidget *window,
3847 gpointer *data)
3848{
3849 GtkClipboard *clipboard;
3850
3851 clipboard = gtk_widget_get_clipboard (window, GDK_SELECTION_CLIPBOARD((GdkAtom)((gpointer) (gulong) (69))));
3852
3853 g_signal_handlers_disconnect_by_func (clipboard,g_signal_handlers_disconnect_matched ((clipboard), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (clipboard_owner_change))), (window))
3854 G_CALLBACK (clipboard_owner_change),g_signal_handlers_disconnect_matched ((clipboard), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (clipboard_owner_change))), (window))
3855 window)g_signal_handlers_disconnect_matched ((clipboard), (GSignalMatchType
) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA), 0, 0, ((void*)
0), (((GCallback) (clipboard_owner_change))), (window))
;
3856}
3857
3858static void
3859check_window_is_active (PlumaWindow *window,
3860 GParamSpec *property,
3861 gpointer useless)
3862{
3863 if (window->priv->window_state & GDK_WINDOW_STATE_FULLSCREEN)
3864 {
3865 if (gtk_window_is_active (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window)))))))
3866 {
3867 gtk_widget_show (window->priv->fullscreen_controls);
3868 }
3869 else
3870 {
3871 gtk_widget_hide (window->priv->fullscreen_controls);
3872 }
3873 }
3874}
3875
3876static void
3877connect_notebook_signals (PlumaWindow *window,
3878 GtkWidget *notebook)
3879{
3880 g_signal_connect (notebook,g_signal_connect_data ((notebook), ("switch-page"), (((GCallback
) (notebook_switch_page))), (window), ((void*)0), (GConnectFlags
) 0)
3881 "switch-page",g_signal_connect_data ((notebook), ("switch-page"), (((GCallback
) (notebook_switch_page))), (window), ((void*)0), (GConnectFlags
) 0)
3882 G_CALLBACK (notebook_switch_page),g_signal_connect_data ((notebook), ("switch-page"), (((GCallback
) (notebook_switch_page))), (window), ((void*)0), (GConnectFlags
) 0)
3883 window)g_signal_connect_data ((notebook), ("switch-page"), (((GCallback
) (notebook_switch_page))), (window), ((void*)0), (GConnectFlags
) 0)
;
3884 g_signal_connect (notebook,g_signal_connect_data ((notebook), ("tab-added"), (((GCallback
) (notebook_tab_added))), (window), ((void*)0), (GConnectFlags
) 0)
3885 "tab-added",g_signal_connect_data ((notebook), ("tab-added"), (((GCallback
) (notebook_tab_added))), (window), ((void*)0), (GConnectFlags
) 0)
3886 G_CALLBACK (notebook_tab_added),g_signal_connect_data ((notebook), ("tab-added"), (((GCallback
) (notebook_tab_added))), (window), ((void*)0), (GConnectFlags
) 0)
3887 window)g_signal_connect_data ((notebook), ("tab-added"), (((GCallback
) (notebook_tab_added))), (window), ((void*)0), (GConnectFlags
) 0)
;
3888 g_signal_connect (notebook,g_signal_connect_data ((notebook), ("tab-removed"), (((GCallback
) (notebook_tab_removed))), (window), ((void*)0), (GConnectFlags
) 0)
3889 "tab-removed",g_signal_connect_data ((notebook), ("tab-removed"), (((GCallback
) (notebook_tab_removed))), (window), ((void*)0), (GConnectFlags
) 0)
3890 G_CALLBACK (notebook_tab_removed),g_signal_connect_data ((notebook), ("tab-removed"), (((GCallback
) (notebook_tab_removed))), (window), ((void*)0), (GConnectFlags
) 0)
3891 window)g_signal_connect_data ((notebook), ("tab-removed"), (((GCallback
) (notebook_tab_removed))), (window), ((void*)0), (GConnectFlags
) 0)
;
3892 g_signal_connect (notebook,g_signal_connect_data ((notebook), ("tabs-reordered"), (((GCallback
) (notebook_tabs_reordered))), (window), ((void*)0), (GConnectFlags
) 0)
3893 "tabs-reordered",g_signal_connect_data ((notebook), ("tabs-reordered"), (((GCallback
) (notebook_tabs_reordered))), (window), ((void*)0), (GConnectFlags
) 0)
3894 G_CALLBACK (notebook_tabs_reordered),g_signal_connect_data ((notebook), ("tabs-reordered"), (((GCallback
) (notebook_tabs_reordered))), (window), ((void*)0), (GConnectFlags
) 0)
3895 window)g_signal_connect_data ((notebook), ("tabs-reordered"), (((GCallback
) (notebook_tabs_reordered))), (window), ((void*)0), (GConnectFlags
) 0)
;
3896 g_signal_connect (notebook,g_signal_connect_data ((notebook), ("tab-detached"), (((GCallback
) (notebook_tab_detached))), (window), ((void*)0), (GConnectFlags
) 0)
3897 "tab-detached",g_signal_connect_data ((notebook), ("tab-detached"), (((GCallback
) (notebook_tab_detached))), (window), ((void*)0), (GConnectFlags
) 0)
3898 G_CALLBACK (notebook_tab_detached),g_signal_connect_data ((notebook), ("tab-detached"), (((GCallback
) (notebook_tab_detached))), (window), ((void*)0), (GConnectFlags
) 0)
3899 window)g_signal_connect_data ((notebook), ("tab-detached"), (((GCallback
) (notebook_tab_detached))), (window), ((void*)0), (GConnectFlags
) 0)
;
3900 g_signal_connect (notebook,g_signal_connect_data ((notebook), ("tab-close-request"), (((
GCallback) (notebook_tab_close_request))), (window), ((void*)
0), (GConnectFlags) 0)
3901 "tab-close-request",g_signal_connect_data ((notebook), ("tab-close-request"), (((
GCallback) (notebook_tab_close_request))), (window), ((void*)
0), (GConnectFlags) 0)
3902 G_CALLBACK (notebook_tab_close_request),g_signal_connect_data ((notebook), ("tab-close-request"), (((
GCallback) (notebook_tab_close_request))), (window), ((void*)
0), (GConnectFlags) 0)
3903 window)g_signal_connect_data ((notebook), ("tab-close-request"), (((
GCallback) (notebook_tab_close_request))), (window), ((void*)
0), (GConnectFlags) 0)
;
3904 g_signal_connect (notebook,g_signal_connect_data ((notebook), ("button-press-event"), ((
(GCallback) (notebook_button_press_event))), (window), ((void
*)0), (GConnectFlags) 0)
3905 "button-press-event",g_signal_connect_data ((notebook), ("button-press-event"), ((
(GCallback) (notebook_button_press_event))), (window), ((void
*)0), (GConnectFlags) 0)
3906 G_CALLBACK (notebook_button_press_event),g_signal_connect_data ((notebook), ("button-press-event"), ((
(GCallback) (notebook_button_press_event))), (window), ((void
*)0), (GConnectFlags) 0)
3907 window)g_signal_connect_data ((notebook), ("button-press-event"), ((
(GCallback) (notebook_button_press_event))), (window), ((void
*)0), (GConnectFlags) 0)
;
3908 g_signal_connect (notebook,g_signal_connect_data ((notebook), ("popup-menu"), (((GCallback
) (notebook_popup_menu))), (window), ((void*)0), (GConnectFlags
) 0)
3909 "popup-menu",g_signal_connect_data ((notebook), ("popup-menu"), (((GCallback
) (notebook_popup_menu))), (window), ((void*)0), (GConnectFlags
) 0)
3910 G_CALLBACK (notebook_popup_menu),g_signal_connect_data ((notebook), ("popup-menu"), (((GCallback
) (notebook_popup_menu))), (window), ((void*)0), (GConnectFlags
) 0)
3911 window)g_signal_connect_data ((notebook), ("popup-menu"), (((GCallback
) (notebook_popup_menu))), (window), ((void*)0), (GConnectFlags
) 0)
;
3912 g_signal_connect (notebook,g_signal_connect_data ((notebook), ("scroll-event"), (((GCallback
) (notebook_scroll_event))), (window), ((void*)0), (GConnectFlags
) 0)
3913 "scroll-event",g_signal_connect_data ((notebook), ("scroll-event"), (((GCallback
) (notebook_scroll_event))), (window), ((void*)0), (GConnectFlags
) 0)
3914 G_CALLBACK (notebook_scroll_event),g_signal_connect_data ((notebook), ("scroll-event"), (((GCallback
) (notebook_scroll_event))), (window), ((void*)0), (GConnectFlags
) 0)
3915 window)g_signal_connect_data ((notebook), ("scroll-event"), (((GCallback
) (notebook_scroll_event))), (window), ((void*)0), (GConnectFlags
) 0)
;
3916}
3917
3918static void
3919add_notebook (PlumaWindow *window,
3920 GtkWidget *notebook)
3921{
3922 gtk_paned_pack1 (GTK_PANED (window->priv->vpaned)((((GtkPaned*) (void *) ((window->priv->vpaned))))),
3923 notebook,
3924 TRUE(!(0)),
3925 TRUE(!(0)));
3926
3927 gtk_widget_show (notebook);
3928
3929 gtk_widget_add_events (notebook, GDK_SCROLL_MASK);
3930 connect_notebook_signals (window, notebook);
3931}
3932
3933static void
3934on_extension_added (PeasExtensionSet *extensions,
3935 PeasPluginInfo *info,
3936 PeasExtension *exten,
3937 PlumaWindow *window)
3938{
3939 peas_extension_call (exten, "activate", window);
3940}
3941
3942static void
3943on_extension_removed (PeasExtensionSet *extensions,
3944 PeasPluginInfo *info,
3945 PeasExtension *exten,
3946 PlumaWindow *window)
3947{
3948 peas_extension_call (exten, "deactivate", window);
3949
3950 /* Ensure update of ui manager, because we suspect it does something
3951 * with expected static strings in the type module (when unloaded the
3952 * strings don't exist anymore, and ui manager updates in an idle
3953 * func) */
3954 gtk_ui_manager_ensure_update (window->priv->manager);
3955}
3956
3957static void
3958pluma_window_init (PlumaWindow *window)
3959{
3960 GtkWidget *main_box;
3961 GtkTargetList *tl;
3962
3963 pluma_debug (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 3963, ((const char*) (__func__
))
);
3964
3965 window->priv = pluma_window_get_instance_private (window);
3966 window->priv->active_tab = NULL((void*)0);
3967 window->priv->num_tabs = 0;
3968 window->priv->removing_tabs = FALSE(0);
3969 window->priv->state = PLUMA_WINDOW_STATE_NORMAL;
3970 window->priv->dispose_has_run = FALSE(0);
3971 window->priv->fullscreen_controls = NULL((void*)0);
3972 window->priv->fullscreen_animation_timeout_id = 0;
3973 window->priv->editor_settings = g_settings_new (PLUMA_SCHEMA_ID"org.mate.pluma");
3974
3975 window->priv->message_bus = pluma_message_bus_new ();
3976
3977 window->priv->window_group = gtk_window_group_new ();
3978 gtk_window_group_add_window (window->priv->window_group, GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
3979
3980 GtkStyleContext *context;
3981
3982 context = gtk_widget_get_style_context (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
3983 gtk_style_context_add_class (context, "pluma-window");
3984
3985 main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
3986 gtk_container_add (GTK_CONTAINER (window)((((GtkContainer*) (void *) ((window))))), main_box);
3987 gtk_widget_show (main_box);
3988
3989 /* Add menu bar and toolbar bar */
3990 create_menu_bar_and_toolbar (window, main_box);
3991
3992 /* Add status bar */
3993 create_statusbar (window, main_box);
3994
3995 /* Add the main area */
3996 pluma_debug_message (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 3996, ((const char*) (__func__
))
, "Add main area");
3997 window->priv->hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
3998 gtk_box_pack_start (GTK_BOX (main_box)((((GtkBox*) (void *) ((main_box))))),
3999 window->priv->hpaned,
4000 TRUE(!(0)),
4001 TRUE(!(0)),
4002 0);
4003
4004 window->priv->vpaned = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
4005 gtk_paned_pack2 (GTK_PANED (window->priv->hpaned)((((GtkPaned*) (void *) ((window->priv->hpaned))))),
4006 window->priv->vpaned,
4007 TRUE(!(0)),
4008 FALSE(0));
4009
4010 pluma_debug_message (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 4010, ((const char*) (__func__
))
, "Create pluma notebook");
4011 window->priv->notebook = pluma_notebook_new ();
4012 add_notebook (window, window->priv->notebook);
4013
4014 /* side and bottom panels */
4015 create_side_panel (window);
4016 create_bottom_panel (window);
4017
4018 /* panes' state must be restored after panels have been mapped,
4019 * since the bottom pane position depends on the size of the vpaned. */
4020 window->priv->side_panel_size = g_settings_get_int (window->priv->editor_settings,
4021 PLUMA_SETTINGS_SIDE_PANEL_SIZE"side-panel-size");
4022 window->priv->bottom_panel_size = g_settings_get_int (window->priv->editor_settings,
4023 PLUMA_SETTINGS_BOTTOM_PANEL_SIZE"bottom-panel-size");
4024
4025 g_signal_connect_after (window->priv->hpaned,g_signal_connect_data ((window->priv->hpaned), ("map"),
(((GCallback) (hpaned_restore_position))), (window), ((void*
)0), G_CONNECT_AFTER)
4026 "map",g_signal_connect_data ((window->priv->hpaned), ("map"),
(((GCallback) (hpaned_restore_position))), (window), ((void*
)0), G_CONNECT_AFTER)
4027 G_CALLBACK (hpaned_restore_position),g_signal_connect_data ((window->priv->hpaned), ("map"),
(((GCallback) (hpaned_restore_position))), (window), ((void*
)0), G_CONNECT_AFTER)
4028 window)g_signal_connect_data ((window->priv->hpaned), ("map"),
(((GCallback) (hpaned_restore_position))), (window), ((void*
)0), G_CONNECT_AFTER)
;
4029 g_signal_connect_after (window->priv->vpaned,g_signal_connect_data ((window->priv->vpaned), ("map"),
(((GCallback) (vpaned_restore_position))), (window), ((void*
)0), G_CONNECT_AFTER)
4030 "map",g_signal_connect_data ((window->priv->vpaned), ("map"),
(((GCallback) (vpaned_restore_position))), (window), ((void*
)0), G_CONNECT_AFTER)
4031 G_CALLBACK (vpaned_restore_position),g_signal_connect_data ((window->priv->vpaned), ("map"),
(((GCallback) (vpaned_restore_position))), (window), ((void*
)0), G_CONNECT_AFTER)
4032 window)g_signal_connect_data ((window->priv->vpaned), ("map"),
(((GCallback) (vpaned_restore_position))), (window), ((void*
)0), G_CONNECT_AFTER)
;
4033
4034 gtk_widget_show (window->priv->hpaned);
4035 gtk_widget_show (window->priv->vpaned);
4036
4037 /* Drag and drop support, set targets to NULL because we add the
4038 default uri_targets below */
4039 gtk_drag_dest_set (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))),
4040 GTK_DEST_DEFAULT_MOTION |
4041 GTK_DEST_DEFAULT_HIGHLIGHT |
4042 GTK_DEST_DEFAULT_DROP,
4043 NULL((void*)0),
4044 0,
4045 GDK_ACTION_COPY);
4046
4047 /* Add uri targets */
4048 tl = gtk_drag_dest_get_target_list (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))));
4049
4050 if (tl == NULL((void*)0))
4051 {
4052 tl = gtk_target_list_new (NULL((void*)0), 0);
4053 gtk_drag_dest_set_target_list (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window))))), tl);
4054 gtk_target_list_unref (tl);
4055 }
4056
4057 gtk_target_list_add_uri_targets (tl, TARGET_URI_LIST);
4058
4059 /* connect instead of override, so that we can
4060 * share the cb code with the view */
4061 g_signal_connect (window,g_signal_connect_data ((window), ("drag_data_received"), (((GCallback
) (drag_data_received_cb))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
4062 "drag_data_received",g_signal_connect_data ((window), ("drag_data_received"), (((GCallback
) (drag_data_received_cb))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
4063 G_CALLBACK (drag_data_received_cb),g_signal_connect_data ((window), ("drag_data_received"), (((GCallback
) (drag_data_received_cb))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
4064 NULL)g_signal_connect_data ((window), ("drag_data_received"), (((GCallback
) (drag_data_received_cb))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
4065
4066 /* we can get the clipboard only after the widget
4067 * is realized */
4068 g_signal_connect (window,g_signal_connect_data ((window), ("realize"), (((GCallback) (
window_realized))), (((void*)0)), ((void*)0), (GConnectFlags)
0)
4069 "realize",g_signal_connect_data ((window), ("realize"), (((GCallback) (
window_realized))), (((void*)0)), ((void*)0), (GConnectFlags)
0)
4070 G_CALLBACK (window_realized),g_signal_connect_data ((window), ("realize"), (((GCallback) (
window_realized))), (((void*)0)), ((void*)0), (GConnectFlags)
0)
4071 NULL)g_signal_connect_data ((window), ("realize"), (((GCallback) (
window_realized))), (((void*)0)), ((void*)0), (GConnectFlags)
0)
;
4072 g_signal_connect (window,g_signal_connect_data ((window), ("unrealize"), (((GCallback)
(window_unrealized))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
4073 "unrealize",g_signal_connect_data ((window), ("unrealize"), (((GCallback)
(window_unrealized))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
4074 G_CALLBACK (window_unrealized),g_signal_connect_data ((window), ("unrealize"), (((GCallback)
(window_unrealized))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
4075 NULL)g_signal_connect_data ((window), ("unrealize"), (((GCallback)
(window_unrealized))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
4076
4077 /* Check if the window is active for fullscreen */
4078 g_signal_connect (window,g_signal_connect_data ((window), ("notify::is-active"), (((GCallback
) (check_window_is_active))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
4079 "notify::is-active",g_signal_connect_data ((window), ("notify::is-active"), (((GCallback
) (check_window_is_active))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
4080 G_CALLBACK (check_window_is_active),g_signal_connect_data ((window), ("notify::is-active"), (((GCallback
) (check_window_is_active))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
4081 NULL)g_signal_connect_data ((window), ("notify::is-active"), (((GCallback
) (check_window_is_active))), (((void*)0)), ((void*)0), (GConnectFlags
) 0)
;
4082
4083 pluma_debug_message (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 4083, ((const char*) (__func__
))
, "Update plugins ui");
4084
4085 window->priv->extensions = peas_extension_set_new (PEAS_ENGINE (pluma_plugins_engine_get_default ())((((PeasEngine*) (void *) ((pluma_plugins_engine_get_default (
))))))
,
4086 PLUMA_TYPE_WINDOW_ACTIVATABLE(pluma_window_activatable_get_type ()),
4087 "window",
4088 window,
4089 NULL((void*)0));
4090
4091 g_signal_connect (window->priv->extensions, "extension-added",g_signal_connect_data ((window->priv->extensions), ("extension-added"
), (((GCallback) (on_extension_added))), (window), ((void*)0)
, (GConnectFlags) 0)
4092 G_CALLBACK (on_extension_added),g_signal_connect_data ((window->priv->extensions), ("extension-added"
), (((GCallback) (on_extension_added))), (window), ((void*)0)
, (GConnectFlags) 0)
4093 window)g_signal_connect_data ((window->priv->extensions), ("extension-added"
), (((GCallback) (on_extension_added))), (window), ((void*)0)
, (GConnectFlags) 0)
;
4094 g_signal_connect (window->priv->extensions, "extension-removed",g_signal_connect_data ((window->priv->extensions), ("extension-removed"
), (((GCallback) (on_extension_removed))), (window), ((void*)
0), (GConnectFlags) 0)
4095 G_CALLBACK (on_extension_removed),g_signal_connect_data ((window->priv->extensions), ("extension-removed"
), (((GCallback) (on_extension_removed))), (window), ((void*)
0), (GConnectFlags) 0)
4096 window)g_signal_connect_data ((window->priv->extensions), ("extension-removed"
), (((GCallback) (on_extension_removed))), (window), ((void*)
0), (GConnectFlags) 0)
;
4097
4098 peas_extension_set_call (window->priv->extensions, "activate");
4099
4100 /* set visibility of panes.
4101 * This needs to be done after plugins activatation */
4102 init_panels_visibility (window);
4103
4104 update_sensitivity_according_to_open_tabs (window);
4105
4106 pluma_debug_message (DEBUG_WINDOWPLUMA_DEBUG_WINDOW, "pluma-window.c", 4106, ((const char*) (__func__
))
, "END");
4107}
4108
4109/**
4110 * pluma_window_get_active_view:
4111 * @window: a #PlumaWindow
4112 *
4113 * Gets the active #PlumaView.
4114 *
4115 * Returns: (transfer none): the active #PlumaView
4116 */
4117PlumaView *
4118pluma_window_get_active_view (PlumaWindow *window)
4119{
4120 PlumaView *view;
4121
4122 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_82
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_82
= 1; else _g_boolean_var_82 = 0; _g_boolean_var_82; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void*)
0)); } } while (0)
;
4123
4124 if (window->priv->active_tab == NULL((void*)0))
4125 return NULL((void*)0);
4126
4127 view = pluma_tab_get_view (PLUMA_TAB (window->priv->active_tab)((((PlumaTab*) (void *) ((window->priv->active_tab))))));
4128
4129 return view;
4130}
4131
4132/**
4133 * pluma_window_get_active_document:
4134 * @window: a #PlumaWindow
4135 *
4136 * Gets the active #PlumaDocument.
4137 *
4138 * Returns: (transfer none): the active #PlumaDocument
4139 */
4140PlumaDocument *
4141pluma_window_get_active_document (PlumaWindow *window)
4142{
4143 PlumaView *view;
4144
4145 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_83
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_83
= 1; else _g_boolean_var_83 = 0; _g_boolean_var_83; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void*)
0)); } } while (0)
;
4146
4147 view = pluma_window_get_active_view (window);
4148 if (view == NULL((void*)0))
4149 return NULL((void*)0);
4150
4151 return PLUMA_DOCUMENT (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)))((((PlumaDocument*) (void *) ((gtk_text_view_get_buffer (((((
GtkTextView*) (void *) ((view)))))))))))
;
4152}
4153
4154GtkWidget *
4155_pluma_window_get_notebook (PlumaWindow *window)
4156{
4157 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_84
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_84
= 1; else _g_boolean_var_84 = 0; _g_boolean_var_84; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void*)
0)); } } while (0)
;
4158
4159 return window->priv->notebook;
4160}
4161
4162/**
4163 * pluma_window_create_tab:
4164 * @window: a #PlumaWindow
4165 * @jump_to: %TRUE to set the new #PlumaTab as active
4166 *
4167 * Creates a new #PlumaTab and adds the new tab to the #PlumaNotebook.
4168 * In case @jump_to is %TRUE the #PlumaNotebook switches to that new #PlumaTab.
4169 *
4170 * Returns: (transfer none): a new #PlumaTab
4171 */
4172PlumaTab *
4173pluma_window_create_tab (PlumaWindow *window,
4174 gboolean jump_to)
4175{
4176 PlumaTab *tab;
4177
4178 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_85
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_85
= 1; else _g_boolean_var_85 = 0; _g_boolean_var_85; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void*)
0)); } } while (0)
;
4179
4180 tab = PLUMA_TAB (_pluma_tab_new ())((((PlumaTab*) (void *) ((_pluma_tab_new ())))));
4181 gtk_widget_show (GTK_WIDGET (tab)((((GtkWidget*) (void *) ((tab))))));
4182
4183 pluma_notebook_add_tab (PLUMA_NOTEBOOK (window->priv->notebook)((((PlumaNotebook*) (void *) ((window->priv->notebook))
)))
,
4184 tab,
4185 -1,
4186 jump_to);
4187
4188 if (!gtk_widget_get_visible (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))))
4189 {
4190 gtk_window_present (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
4191 }
4192
4193 return tab;
4194}
4195
4196/**
4197 * pluma_window_create_tab_from_uri:
4198 * @window: a #PlumaWindow
4199 * @uri: the uri of the document
4200 * @encoding: a #PlumaEncoding
4201 * @line_pos: the line position to visualize
4202 * @create: %TRUE to create a new document in case @uri does exist
4203 * @jump_to: %TRUE to set the new #PlumaTab as active
4204 *
4205 * Creates a new #PlumaTab loading the document specified by @uri.
4206 * In case @jump_to is %TRUE the #PlumaNotebook swithes to that new #PlumaTab.
4207 * Whether @create is %TRUE, creates a new empty document if location does
4208 * not refer to an existing file
4209 *
4210 * Returns: (transfer none): a new #PlumaTab
4211 */
4212PlumaTab *
4213pluma_window_create_tab_from_uri (PlumaWindow *window,
4214 const gchar *uri,
4215 const PlumaEncoding *encoding,
4216 gint line_pos,
4217 gboolean create,
4218 gboolean jump_to)
4219{
4220 GtkWidget *tab;
4221
4222 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_86
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_86
= 1; else _g_boolean_var_86 = 0; _g_boolean_var_86; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void*)
0)); } } while (0)
;
4223 g_return_val_if_fail (uri != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_87
; if (uri != ((void*)0)) _g_boolean_var_87 = 1; else _g_boolean_var_87
= 0; _g_boolean_var_87; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "uri != NULL"); return
(((void*)0)); } } while (0)
;
4224
4225 tab = _pluma_tab_new_from_uri (uri,
4226 encoding,
4227 line_pos,
4228 create);
4229 if (tab == NULL((void*)0))
4230 return NULL((void*)0);
4231
4232 gtk_widget_show (tab);
4233
4234 pluma_notebook_add_tab (PLUMA_NOTEBOOK (window->priv->notebook)((((PlumaNotebook*) (void *) ((window->priv->notebook))
)))
,
4235 PLUMA_TAB (tab)((((PlumaTab*) (void *) ((tab))))),
4236 -1,
4237 jump_to);
4238
4239 if (!gtk_widget_get_visible (GTK_WIDGET (window)((((GtkWidget*) (void *) ((window)))))))
4240 {
4241 gtk_window_present (GTK_WINDOW (window)((((GtkWindow*) (void *) ((window))))));
4242 }
4243
4244 return PLUMA_TAB (tab)((((PlumaTab*) (void *) ((tab)))));
4245}
4246
4247/**
4248 * pluma_window_get_active_tab:
4249 * @window: a PlumaWindow
4250 *
4251 * Gets the active #PlumaTab in the @window.
4252 *
4253 * Returns: (transfer none): the active #PlumaTab in the @window.
4254 */
4255PlumaTab *
4256pluma_window_get_active_tab (PlumaWindow *window)
4257{
4258 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_88
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_88
= 1; else _g_boolean_var_88 = 0; _g_boolean_var_88; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void*)
0)); } } while (0)
;
4259
4260 return (window->priv->active_tab == NULL((void*)0)) ?
4261 NULL((void*)0) : PLUMA_TAB (window->priv->active_tab)((((PlumaTab*) (void *) ((window->priv->active_tab)))));
4262}
4263
4264static void
4265add_document (PlumaTab *tab, GList **res)
4266{
4267 PlumaDocument *doc;
4268
4269 doc = pluma_tab_get_document (tab);
4270
4271 *res = g_list_prepend (*res, doc);
4272}
4273
4274/**
4275 * pluma_window_get_documents:
4276 * @window: a #PlumaWindow
4277 *
4278 * Gets a newly allocated list with all the documents in the window.
4279 * This list must be freed.
4280 *
4281 * Returns: (element-type Pluma.Document) (transfer container): a newly
4282 * allocated list with all the documents in the window
4283 */
4284GList *
4285pluma_window_get_documents (PlumaWindow *window)
4286{
4287 GList *res = NULL((void*)0);
4288
4289 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_89
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_89
= 1; else _g_boolean_var_89 = 0; _g_boolean_var_89; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void*)
0)); } } while (0)
;
4290
4291 gtk_container_foreach (GTK_CONTAINER (window->priv->notebook)((((GtkContainer*) (void *) ((window->priv->notebook)))
))
,
4292 (GtkCallback)add_document,
4293 &res);
4294
4295 res = g_list_reverse (res);
4296
4297 return res;
4298}
4299
4300static void
4301add_view (PlumaTab *tab, GList **res)
4302{
4303 PlumaView *view;
4304
4305 view = pluma_tab_get_view (tab);
4306
4307 *res = g_list_prepend (*res, view);
4308}
4309
4310/**
4311 * pluma_window_get_views:
4312 * @window: a #PlumaWindow
4313 *
4314 * Gets a list with all the views in the window. This list must be freed.
4315 *
4316 * Returns: (element-type Pluma.View) (transfer container): a newly allocated
4317 * list with all the views in the window
4318 */
4319GList *
4320pluma_window_get_views (PlumaWindow *window)
4321{
4322 GList *res = NULL((void*)0);
4323
4324 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_90
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_90
= 1; else _g_boolean_var_90 = 0; _g_boolean_var_90; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void*)
0)); } } while (0)
;
4325
4326 gtk_container_foreach (GTK_CONTAINER (window->priv->notebook)((((GtkContainer*) (void *) ((window->priv->notebook)))
))
,
4327 (GtkCallback)add_view,
4328 &res);
4329
4330 res = g_list_reverse (res);
4331
4332 return res;
4333}
4334
4335/**
4336 * pluma_window_close_tab:
4337 * @window: a #PlumaWindow
4338 * @tab: the #PlumaTab to close
4339 *
4340 * Closes the @tab.
4341 */
4342void
4343pluma_window_close_tab (PlumaWindow *window,
4344 PlumaTab *tab)
4345{
4346 g_return_if_fail (PLUMA_IS_WINDOW (window))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_91
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_91
= 1; else _g_boolean_var_91 = 0; _g_boolean_var_91; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "PLUMA_IS_WINDOW (window)"); return; } } while
(0)
;
4347 g_return_if_fail (PLUMA_IS_TAB (tab))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_92
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tab)); GType __t = ((pluma_tab_get_type())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_92
= 1; else _g_boolean_var_92 = 0; _g_boolean_var_92; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "PLUMA_IS_TAB (tab)"); return; } } while (0)
;
4348 g_return_if_fail ((pluma_tab_get_state (tab) != PLUMA_TAB_STATE_SAVING) &&do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_93
; if ((pluma_tab_get_state (tab) != PLUMA_TAB_STATE_SAVING) &&
(pluma_tab_get_state (tab) != PLUMA_TAB_STATE_SHOWING_PRINT_PREVIEW
)) _g_boolean_var_93 = 1; else _g_boolean_var_93 = 0; _g_boolean_var_93
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "(pluma_tab_get_state (tab) != PLUMA_TAB_STATE_SAVING) && (pluma_tab_get_state (tab) != PLUMA_TAB_STATE_SHOWING_PRINT_PREVIEW)"
); return; } } while (0)
4349 (pluma_tab_get_state (tab) != PLUMA_TAB_STATE_SHOWING_PRINT_PREVIEW))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_93
; if ((pluma_tab_get_state (tab) != PLUMA_TAB_STATE_SAVING) &&
(pluma_tab_get_state (tab) != PLUMA_TAB_STATE_SHOWING_PRINT_PREVIEW
)) _g_boolean_var_93 = 1; else _g_boolean_var_93 = 0; _g_boolean_var_93
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "(pluma_tab_get_state (tab) != PLUMA_TAB_STATE_SAVING) && (pluma_tab_get_state (tab) != PLUMA_TAB_STATE_SHOWING_PRINT_PREVIEW)"
); return; } } while (0)
;
4350
4351 pluma_notebook_remove_tab (PLUMA_NOTEBOOK (window->priv->notebook)((((PlumaNotebook*) (void *) ((window->priv->notebook))
)))
, tab);
4352}
4353
4354/**
4355 * pluma_window_close_all_tabs:
4356 * @window: a #PlumaWindow
4357 *
4358 * Closes all opened tabs.
4359 */
4360void
4361pluma_window_close_all_tabs (PlumaWindow *window)
4362{
4363 g_return_if_fail (PLUMA_IS_WINDOW (window))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_94
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_94
= 1; else _g_boolean_var_94 = 0; _g_boolean_var_94; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "PLUMA_IS_WINDOW (window)"); return; } } while
(0)
;
4364 g_return_if_fail (!(window->priv->state & PLUMA_WINDOW_STATE_SAVING) &&do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_95
; if (!(window->priv->state & PLUMA_WINDOW_STATE_SAVING
) && !(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION
)) _g_boolean_var_95 = 1; else _g_boolean_var_95 = 0; _g_boolean_var_95
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "!(window->priv->state & PLUMA_WINDOW_STATE_SAVING) && !(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION)"
); return; } } while (0)
4365 !(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_95
; if (!(window->priv->state & PLUMA_WINDOW_STATE_SAVING
) && !(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION
)) _g_boolean_var_95 = 1; else _g_boolean_var_95 = 0; _g_boolean_var_95
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "!(window->priv->state & PLUMA_WINDOW_STATE_SAVING) && !(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION)"
); return; } } while (0)
;
4366
4367 window->priv->removing_tabs = TRUE(!(0));
4368
4369 pluma_notebook_remove_all_tabs (PLUMA_NOTEBOOK (window->priv->notebook)((((PlumaNotebook*) (void *) ((window->priv->notebook))
)))
);
4370
4371 window->priv->removing_tabs = FALSE(0);
4372}
4373
4374/**
4375 * pluma_window_close_tabs:
4376 * @window: a #PlumaWindow
4377 * @tabs: (element-type Pluma.Tab): a list of #PlumaTab
4378 *
4379 * Closes all tabs specified by @tabs.
4380 */
4381void
4382pluma_window_close_tabs (PlumaWindow *window,
4383 const GList *tabs)
4384{
4385 g_return_if_fail (PLUMA_IS_WINDOW (window))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_96
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_96
= 1; else _g_boolean_var_96 = 0; _g_boolean_var_96; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "PLUMA_IS_WINDOW (window)"); return; } } while
(0)
;
4386 g_return_if_fail (!(window->priv->state & PLUMA_WINDOW_STATE_SAVING) &&do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_97
; if (!(window->priv->state & PLUMA_WINDOW_STATE_SAVING
) && !(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION
)) _g_boolean_var_97 = 1; else _g_boolean_var_97 = 0; _g_boolean_var_97
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "!(window->priv->state & PLUMA_WINDOW_STATE_SAVING) && !(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION)"
); return; } } while (0)
4387 !(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_97
; if (!(window->priv->state & PLUMA_WINDOW_STATE_SAVING
) && !(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION
)) _g_boolean_var_97 = 1; else _g_boolean_var_97 = 0; _g_boolean_var_97
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "!(window->priv->state & PLUMA_WINDOW_STATE_SAVING) && !(window->priv->state & PLUMA_WINDOW_STATE_SAVING_SESSION)"
); return; } } while (0)
;
4388
4389 if (tabs == NULL((void*)0))
4390 return;
4391
4392 window->priv->removing_tabs = TRUE(!(0));
4393
4394 while (tabs != NULL((void*)0))
4395 {
4396 if (tabs->next == NULL((void*)0))
4397 window->priv->removing_tabs = FALSE(0);
4398
4399 pluma_notebook_remove_tab (PLUMA_NOTEBOOK (window->priv->notebook)((((PlumaNotebook*) (void *) ((window->priv->notebook))
)))
,
4400 PLUMA_TAB (tabs->data)((((PlumaTab*) (void *) ((tabs->data))))));
4401
4402 tabs = g_list_next (tabs)((tabs) ? (((GList *)(tabs))->next) : ((void*)0));
4403 }
4404
4405 g_return_if_fail (window->priv->removing_tabs == FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_98
; if (window->priv->removing_tabs == (0)) _g_boolean_var_98
= 1; else _g_boolean_var_98 = 0; _g_boolean_var_98; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "window->priv->removing_tabs == FALSE")
; return; } } while (0)
;
4406}
4407
4408PlumaWindow *
4409_pluma_window_move_tab_to_new_window (PlumaWindow *window,
4410 PlumaTab *tab)
4411{
4412 PlumaWindow *new_window;
4413
4414 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_99
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_99
= 1; else _g_boolean_var_99 = 0; _g_boolean_var_99; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void*)
0)); } } while (0)
;
4415 g_return_val_if_fail (PLUMA_IS_TAB (tab), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_100
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tab)); GType __t = ((pluma_tab_get_type())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_100
= 1; else _g_boolean_var_100 = 0; _g_boolean_var_100; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_TAB (tab)"); return (((void*)0
)); } } while (0)
;
4416 g_return_val_if_fail (gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->priv->notebook)) > 1,do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_101
; if (gtk_notebook_get_n_pages (((((GtkNotebook*) (void *) ((
window->priv->notebook)))))) > 1) _g_boolean_var_101
= 1; else _g_boolean_var_101 = 0; _g_boolean_var_101; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->priv->notebook)) > 1"
); return (((void*)0)); } } while (0)
4417 NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_101
; if (gtk_notebook_get_n_pages (((((GtkNotebook*) (void *) ((
window->priv->notebook)))))) > 1) _g_boolean_var_101
= 1; else _g_boolean_var_101 = 0; _g_boolean_var_101; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "gtk_notebook_get_n_pages (GTK_NOTEBOOK (window->priv->notebook)) > 1"
); return (((void*)0)); } } while (0)
;
4418
4419 new_window = clone_window (window);
4420
4421 pluma_notebook_move_tab (PLUMA_NOTEBOOK (window->priv->notebook)((((PlumaNotebook*) (void *) ((window->priv->notebook))
)))
,
4422 PLUMA_NOTEBOOK (new_window->priv->notebook)((((PlumaNotebook*) (void *) ((new_window->priv->notebook
)))))
,
4423 tab,
4424 -1);
4425
4426 gtk_widget_show (GTK_WIDGET (new_window)((((GtkWidget*) (void *) ((new_window))))));
4427
4428 return new_window;
4429}
4430
4431/**
4432 * pluma_window_set_active_tab:
4433 * @window: a #PlumaWindow
4434 * @tab: a #PlumaTab
4435 *
4436 * Switches to the tab that matches with @tab.
4437 */
4438void
4439pluma_window_set_active_tab (PlumaWindow *window,
4440 PlumaTab *tab)
4441{
4442 gint page_num;
4443
4444 g_return_if_fail (PLUMA_IS_WINDOW (window))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_102
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_102
= 1; else _g_boolean_var_102 = 0; _g_boolean_var_102; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return; } }
while (0)
;
4445 g_return_if_fail (PLUMA_IS_TAB (tab))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_103
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tab)); GType __t = ((pluma_tab_get_type())); gboolean __r
; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_103
= 1; else _g_boolean_var_103 = 0; _g_boolean_var_103; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_TAB (tab)"); return; } } while
(0)
;
4446
4447 page_num = gtk_notebook_page_num (GTK_NOTEBOOK (window->priv->notebook)((((GtkNotebook*) (void *) ((window->priv->notebook))))
)
,
4448 GTK_WIDGET (tab)((((GtkWidget*) (void *) ((tab))))));
4449 g_return_if_fail (page_num != -1)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_104
; if (page_num != -1) _g_boolean_var_104 = 1; else _g_boolean_var_104
= 0; _g_boolean_var_104; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "page_num != -1")
; return; } } while (0)
;
4450
4451 gtk_notebook_set_current_page (GTK_NOTEBOOK (window->priv->notebook)((((GtkNotebook*) (void *) ((window->priv->notebook))))
)
,
4452 page_num);
4453}
4454
4455/**
4456 * pluma_window_get_group:
4457 * @window: a #PlumaWindow
4458 *
4459 * Gets the #GtkWindowGroup in which @window resides.
4460 *
4461 * Returns: (transfer none): the #GtkWindowGroup
4462 */
4463GtkWindowGroup *
4464pluma_window_get_group (PlumaWindow *window)
4465{
4466 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_105
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_105
= 1; else _g_boolean_var_105 = 0; _g_boolean_var_105; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void
*)0)); } } while (0)
;
4467
4468 return window->priv->window_group;
4469}
4470
4471gboolean
4472_pluma_window_is_removing_tabs (PlumaWindow *window)
4473{
4474 g_return_val_if_fail (PLUMA_IS_WINDOW (window), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_106
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_106
= 1; else _g_boolean_var_106 = 0; _g_boolean_var_106; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return ((0)
); } } while (0)
;
4475
4476 return window->priv->removing_tabs;
4477}
4478
4479/**
4480 * pluma_window_get_ui_manager:
4481 * @window: a #PlumaWindow
4482 *
4483 * Gets the #GtkUIManager associated with the @window.
4484 *
4485 * Returns: (transfer none): the #GtkUIManager of the @window.
4486 */
4487GtkUIManager *
4488pluma_window_get_ui_manager (PlumaWindow *window)
4489{
4490 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_107
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_107
= 1; else _g_boolean_var_107 = 0; _g_boolean_var_107; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void
*)0)); } } while (0)
;
4491
4492 return window->priv->manager;
4493}
4494
4495/**
4496 * pluma_window_get_side_panel:
4497 * @window: a #PlumaWindow
4498 *
4499 * Gets the side #PlumaPanel of the @window.
4500 *
4501 * Returns: (transfer none): the side #PlumaPanel.
4502 */
4503PlumaPanel *
4504pluma_window_get_side_panel (PlumaWindow *window)
4505{
4506 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_108
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_108
= 1; else _g_boolean_var_108 = 0; _g_boolean_var_108; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void
*)0)); } } while (0)
;
4507
4508 return PLUMA_PANEL (window->priv->side_panel)((((PlumaPanel*) (void *) ((window->priv->side_panel)))
))
;
4509}
4510
4511/**
4512 * pluma_window_get_bottom_panel:
4513 * @window: a #PlumaWindow
4514 *
4515 * Gets the bottom #PlumaPanel of the @window.
4516 *
4517 * Returns: (transfer none): the bottom #PlumaPanel.
4518 */
4519PlumaPanel *
4520pluma_window_get_bottom_panel (PlumaWindow *window)
4521{
4522 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_109
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_109
= 1; else _g_boolean_var_109 = 0; _g_boolean_var_109; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void
*)0)); } } while (0)
;
4523
4524 return PLUMA_PANEL (window->priv->bottom_panel)((((PlumaPanel*) (void *) ((window->priv->bottom_panel)
))))
;
4525}
4526
4527/**
4528 * pluma_window_get_statusbar:
4529 * @window: a #PlumaWindow
4530 *
4531 * Gets the #PlumaStatusbar of the @window.
4532 *
4533 * Returns: (transfer none): the #PlumaStatusbar of the @window.
4534 */
4535GtkWidget *
4536pluma_window_get_statusbar (PlumaWindow *window)
4537{
4538 g_return_val_if_fail (PLUMA_IS_WINDOW (window), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_110
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_110
= 1; else _g_boolean_var_110 = 0; _g_boolean_var_110; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (0);
} } while (0)
;
4539
4540 return window->priv->statusbar;
4541}
4542
4543/**
4544 * pluma_window_get_state:
4545 * @window: a #PlumaWindow
4546 *
4547 * Retrieves the state of the @window.
4548 *
4549 * Returns: the current #PlumaWindowState of the @window.
4550 */
4551PlumaWindowState
4552pluma_window_get_state (PlumaWindow *window)
4553{
4554 g_return_val_if_fail (PLUMA_IS_WINDOW (window), PLUMA_WINDOW_STATE_NORMAL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_111
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_111
= 1; else _g_boolean_var_111 = 0; _g_boolean_var_111; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (PLUMA_WINDOW_STATE_NORMAL
); } } while (0)
;
4555
4556 return window->priv->state;
4557}
4558
4559GFile *
4560_pluma_window_get_default_location (PlumaWindow *window)
4561{
4562 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_112
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_112
= 1; else _g_boolean_var_112 = 0; _g_boolean_var_112; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void
*)0)); } } while (0)
;
4563
4564 return window->priv->default_location != NULL((void*)0) ?
4565 g_object_ref (window->priv->default_location)((__typeof__ (window->priv->default_location)) (g_object_ref
) (window->priv->default_location))
: NULL((void*)0);
4566}
4567
4568void
4569_pluma_window_set_default_location (PlumaWindow *window,
4570 GFile *location)
4571{
4572 GFile *dir;
4573
4574 g_return_if_fail (PLUMA_IS_WINDOW (window))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_113
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_113
= 1; else _g_boolean_var_113 = 0; _g_boolean_var_113; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return; } }
while (0)
;
4575 g_return_if_fail (G_IS_FILE (location))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_114
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((location)); GType __t = ((g_file_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_114
= 1; else _g_boolean_var_114 = 0; _g_boolean_var_114; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "G_IS_FILE (location)"); return; } } while
(0)
;
4576
4577 dir = g_file_get_parent (location);
4578 g_return_if_fail (dir != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_115
; if (dir != ((void*)0)) _g_boolean_var_115 = 1; else _g_boolean_var_115
= 0; _g_boolean_var_115; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "dir != NULL"); return
; } } while (0)
;
4579
4580 if (window->priv->default_location != NULL((void*)0))
4581 g_object_unref (window->priv->default_location);
4582
4583 window->priv->default_location = dir;
4584}
4585
4586/**
4587 * pluma_window_get_unsaved_documents:
4588 * @window: a #PlumaWindow
4589 *
4590 * Gets the list of documents that need to be saved before closing the window.
4591 *
4592 * Returns: (element-type Pluma.Document) (transfer container): a list of
4593 * #PlumaDocument that need to be saved before closing the window
4594 */
4595GList *
4596pluma_window_get_unsaved_documents (PlumaWindow *window)
4597{
4598 GList *unsaved_docs = NULL((void*)0);
4599 GList *tabs;
4600 GList *l;
4601
4602 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_116
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_116
= 1; else _g_boolean_var_116 = 0; _g_boolean_var_116; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void
*)0)); } } while (0)
;
4603
4604 tabs = gtk_container_get_children (GTK_CONTAINER (window->priv->notebook)((((GtkContainer*) (void *) ((window->priv->notebook)))
))
);
4605
4606 l = tabs;
4607 while (l != NULL((void*)0))
4608 {
4609 PlumaTab *tab;
4610
4611 tab = PLUMA_TAB (l->data)((((PlumaTab*) (void *) ((l->data)))));
4612
4613 if (!_pluma_tab_can_close (tab))
4614 {
4615 PlumaDocument *doc;
4616
4617 doc = pluma_tab_get_document (tab);
4618 unsaved_docs = g_list_prepend (unsaved_docs, doc);
4619 }
4620
4621 l = g_list_next (l)((l) ? (((GList *)(l))->next) : ((void*)0));
4622 }
4623
4624 g_list_free (tabs);
4625
4626 return g_list_reverse (unsaved_docs);
4627}
4628
4629void
4630_pluma_window_set_saving_session_state (PlumaWindow *window,
4631 gboolean saving_session)
4632{
4633 PlumaWindowState old_state;
4634
4635 g_return_if_fail (PLUMA_IS_WINDOW (window))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_117
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_117
= 1; else _g_boolean_var_117 = 0; _g_boolean_var_117; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return; } }
while (0)
;
4636
4637 old_state = window->priv->state;
4638
4639 if (saving_session)
4640 window->priv->state |= PLUMA_WINDOW_STATE_SAVING_SESSION;
4641 else
4642 window->priv->state &= ~PLUMA_WINDOW_STATE_SAVING_SESSION;
4643
4644 if (old_state != window->priv->state)
4645 {
4646 set_sensitivity_according_to_window_state (window);
4647
4648 g_object_notify (G_OBJECT (window)((((GObject*) (void *) ((window))))), "state");
4649 }
4650}
4651
4652static void
4653hide_notebook_tabs_on_fullscreen (GtkNotebook *notebook,
4654 GParamSpec *pspec,
4655 PlumaWindow *window)
4656{
4657 gtk_notebook_set_show_tabs (notebook, FALSE(0));
4658}
4659
4660void
4661_pluma_window_fullscreen (PlumaWindow *window)
4662{
4663 g_return_if_fail (PLUMA_IS_WINDOW (window))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_118
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_118
= 1; else _g_boolean_var_118 = 0; _g_boolean_var_118; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return; } }
while (0)
;
4664
4665 if (_pluma_window_is_fullscreen (window))
4666 return;
4667
4668 /* Go to fullscreen mode and hide bars */
4669 gtk_window_fullscreen (&window->window);
4670 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (window->priv->notebook)((((GtkNotebook*) (void *) ((window->priv->notebook))))
)
, FALSE(0));
4671 g_signal_connect (window->priv->notebook, "notify::show-tabs",g_signal_connect_data ((window->priv->notebook), ("notify::show-tabs"
), (((GCallback) (hide_notebook_tabs_on_fullscreen))), (window
), ((void*)0), (GConnectFlags) 0)
4672 G_CALLBACK (hide_notebook_tabs_on_fullscreen), window)g_signal_connect_data ((window->priv->notebook), ("notify::show-tabs"
), (((GCallback) (hide_notebook_tabs_on_fullscreen))), (window
), ((void*)0), (GConnectFlags) 0)
;
4673
4674 gtk_widget_hide (window->priv->menubar);
4675
4676 g_signal_handlers_block_by_func (window->priv->toolbar,g_signal_handlers_block_matched ((window->priv->toolbar
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (toolbar_visibility_changed), (window))
4677 toolbar_visibility_changed,g_signal_handlers_block_matched ((window->priv->toolbar
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (toolbar_visibility_changed), (window))
4678 window)g_signal_handlers_block_matched ((window->priv->toolbar
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (toolbar_visibility_changed), (window))
;
4679 gtk_widget_hide (window->priv->toolbar);
4680
4681 g_signal_handlers_block_by_func (window->priv->statusbar,g_signal_handlers_block_matched ((window->priv->statusbar
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (statusbar_visibility_changed), (window)
)
4682 statusbar_visibility_changed,g_signal_handlers_block_matched ((window->priv->statusbar
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (statusbar_visibility_changed), (window)
)
4683 window)g_signal_handlers_block_matched ((window->priv->statusbar
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (statusbar_visibility_changed), (window)
)
;
4684 gtk_widget_hide (window->priv->statusbar);
4685
4686 fullscreen_controls_build (window);
4687 fullscreen_controls_show (window);
4688}
4689
4690void
4691_pluma_window_unfullscreen (PlumaWindow *window)
4692{
4693 gboolean visible;
4694 GtkAction *action;
4695
4696 g_return_if_fail (PLUMA_IS_WINDOW (window))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_119
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_119
= 1; else _g_boolean_var_119 = 0; _g_boolean_var_119; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return; } }
while (0)
;
4697
4698 if (!_pluma_window_is_fullscreen (window))
4699 return;
4700
4701 /* Unfullscreen and show bars */
4702 gtk_window_unfullscreen (&window->window);
4703 g_signal_handlers_disconnect_by_func (window->priv->notebook,g_signal_handlers_disconnect_matched ((window->priv->notebook
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (hide_notebook_tabs_on_fullscreen), (window
))
4704 hide_notebook_tabs_on_fullscreen,g_signal_handlers_disconnect_matched ((window->priv->notebook
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (hide_notebook_tabs_on_fullscreen), (window
))
4705 window)g_signal_handlers_disconnect_matched ((window->priv->notebook
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (hide_notebook_tabs_on_fullscreen), (window
))
;
4706 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (window->priv->notebook)((((GtkNotebook*) (void *) ((window->priv->notebook))))
)
, TRUE(!(0)));
4707 gtk_widget_show (window->priv->menubar);
4708
4709 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group,
4710 "ViewToolbar");
4711 visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action))))));
4712 if (visible)
4713 gtk_widget_show (window->priv->toolbar);
4714 g_signal_handlers_unblock_by_func (window->priv->toolbar,g_signal_handlers_unblock_matched ((window->priv->toolbar
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (toolbar_visibility_changed), (window))
4715 toolbar_visibility_changed,g_signal_handlers_unblock_matched ((window->priv->toolbar
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (toolbar_visibility_changed), (window))
4716 window)g_signal_handlers_unblock_matched ((window->priv->toolbar
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (toolbar_visibility_changed), (window))
;
4717
4718 action = gtk_action_group_get_action (window->priv->always_sensitive_action_group,
4719 "ViewStatusbar");
4720 visible = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)((((GtkToggleAction*) (void *) ((action))))));
4721 if (visible)
4722 gtk_widget_show (window->priv->statusbar);
4723 g_signal_handlers_unblock_by_func (window->priv->statusbar,g_signal_handlers_unblock_matched ((window->priv->statusbar
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (statusbar_visibility_changed), (window)
)
4724 statusbar_visibility_changed,g_signal_handlers_unblock_matched ((window->priv->statusbar
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (statusbar_visibility_changed), (window)
)
4725 window)g_signal_handlers_unblock_matched ((window->priv->statusbar
), (GSignalMatchType) (G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA
), 0, 0, ((void*)0), (statusbar_visibility_changed), (window)
)
;
4726
4727 gtk_widget_hide (window->priv->fullscreen_controls);
4728}
4729
4730gboolean
4731_pluma_window_is_fullscreen (PlumaWindow *window)
4732{
4733 g_return_val_if_fail (PLUMA_IS_WINDOW (window), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_120
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_120
= 1; else _g_boolean_var_120 = 0; _g_boolean_var_120; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return ((0)
); } } while (0)
;
4734
4735 return window->priv->window_state & GDK_WINDOW_STATE_FULLSCREEN;
4736}
4737
4738/**
4739 * pluma_window_get_tab_from_location:
4740 * @window: a #PlumaWindow
4741 * @location: a #GFile
4742 *
4743 * Gets the #PlumaTab that matches with the given @location.
4744 *
4745 * Returns: (transfer none): the #PlumaTab that matches with the given @location.
4746 */
4747PlumaTab *
4748pluma_window_get_tab_from_location (PlumaWindow *window,
4749 GFile *location)
4750{
4751 GList *tabs;
4752 GList *l;
4753 PlumaTab *ret = NULL((void*)0);
4754
4755 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_121
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_121
= 1; else _g_boolean_var_121 = 0; _g_boolean_var_121; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void
*)0)); } } while (0)
;
4756 g_return_val_if_fail (G_IS_FILE (location), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_122
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((location)); GType __t = ((g_file_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_122
= 1; else _g_boolean_var_122 = 0; _g_boolean_var_122; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "G_IS_FILE (location)"); return (((void*
)0)); } } while (0)
;
4757
4758 tabs = gtk_container_get_children (GTK_CONTAINER (window->priv->notebook)((((GtkContainer*) (void *) ((window->priv->notebook)))
))
);
4759
4760 for (l = tabs; l != NULL((void*)0); l = g_list_next (l)((l) ? (((GList *)(l))->next) : ((void*)0)))
4761 {
4762 PlumaDocument *d;
4763 PlumaTab *t;
4764 GFile *f;
4765
4766 t = PLUMA_TAB (l->data)((((PlumaTab*) (void *) ((l->data)))));
4767 d = pluma_tab_get_document (t);
4768
4769 f = pluma_document_get_location (d);
4770
4771 if ((f != NULL((void*)0)))
4772 {
4773 gboolean found = g_file_equal (location, f);
4774
4775 g_object_unref (f);
4776
4777 if (found)
4778 {
4779 ret = t;
4780 break;
4781 }
4782 }
4783 }
4784
4785 g_list_free (tabs);
4786
4787 return ret;
4788}
4789
4790/**
4791 * pluma_window_get_message_bus:
4792 * @window: a #PlumaWindow
4793 *
4794 * Gets the #PlumaMessageBus associated with @window. The returned reference
4795 * is owned by the window and should not be unreffed.
4796 *
4797 * Return value: (transfer none): the #PlumaMessageBus associated with @window
4798 */
4799PlumaMessageBus *
4800pluma_window_get_message_bus (PlumaWindow *window)
4801{
4802 g_return_val_if_fail (PLUMA_IS_WINDOW (window), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_123
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((window)); GType __t = ((pluma_window_get_type())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_123
= 1; else _g_boolean_var_123 = 0; _g_boolean_var_123; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "PLUMA_IS_WINDOW (window)"); return (((void
*)0)); } } while (0)
;
4803
4804 return window->priv->message_bus;
4805}
4806
4807void
4808_pluma_window_get_default_size (gint *width, gint *height)
4809{
4810 g_return_if_fail (width != NULL && height != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_124
; if (width != ((void*)0) && height != ((void*)0)) _g_boolean_var_124
= 1; else _g_boolean_var_124 = 0; _g_boolean_var_124; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "width != NULL && height != NULL"
); return; } } while (0)
;
4811
4812 *width = PLUMA_WINDOW_DEFAULT_WIDTH650;
4813 *height = PLUMA_WINDOW_DEFAULT_HEIGHT500;
4814}
4815
diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-4a60ca.html b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-4a60ca.html new file mode 100644 index 00000000..1393b9bf --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-4a60ca.html @@ -0,0 +1,4233 @@ + + + +pluma-file-browser-store.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:plugins/filebrowser/pluma-file-browser-store.c
Warning:line 577, column 6
Value stored to 'node' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pluma-file-browser-store.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/plugins/filebrowser -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I ../.. -I ../.. -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/gtksourceview-4 -I /usr/include/libpeas-1.0 -I /usr/include/gobject-introspection-1.0 -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/plugins/filebrowser -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-10-22-114445-13211-1 -x c pluma-file-browser-store.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * pluma-file-browser-store.c - Pluma plugin providing easy file access
3 * from the sidepanel
4 *
5 * Copyright (C) 2006 - Jesse van den Kieboom <jesse@icecrew.nl>
6 * Copyright (C) 2012-2021 MATE Developers
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23#ifdef HAVE_CONFIG_H1
24#include <config.h>
25#endif
26
27#include <string.h>
28#include <glib/gi18n-lib.h>
29#include <gio/gio.h>
30
31#include "pluma-file-browser-store.h"
32#include "pluma-file-browser-enum-types.h"
33#include "pluma-file-browser-error.h"
34#include "pluma-file-browser-utils.h"
35
36#define NODE_IS_DIR(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
(FILE_IS_DIR((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
)
)
37#define NODE_IS_HIDDEN(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
))
(FILE_IS_HIDDEN((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
)
)
38#define NODE_IS_TEXT(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_TEXT
))
(FILE_IS_TEXT((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_TEXT
)
)
39#define NODE_LOADED(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
(FILE_LOADED((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED))
40#define NODE_IS_FILTERED(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED
))
(FILE_IS_FILTERED((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED
)
)
41#define NODE_IS_DUMMY(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
(FILE_IS_DUMMY((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
)
)
42
43#define FILE_BROWSER_NODE_DIR(node)((FileBrowserNodeDir *)(node)) ((FileBrowserNodeDir *)(node))
44
45#define DIRECTORY_LOAD_ITEMS_PER_CALLBACK100 100
46#define STANDARD_ATTRIBUTE_TYPES"standard::type" "," "standard::is-hidden" "," "standard::is-backup"
"," "standard::name" "," "standard::content-type" "," "standard::icon"
G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type" "," \
47 G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN"standard::is-hidden" "," \
48 G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP"standard::is-backup" "," \
49 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name" "," \
50 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE"standard::content-type" "," \
51 G_FILE_ATTRIBUTE_STANDARD_ICON"standard::icon"
52
53typedef struct _FileBrowserNode FileBrowserNode;
54typedef struct _FileBrowserNodeDir FileBrowserNodeDir;
55typedef struct _AsyncData AsyncData;
56typedef struct _AsyncNode AsyncNode;
57
58typedef gint (*SortFunc) (FileBrowserNode * node1,
59 FileBrowserNode * node2);
60
61struct _AsyncData
62{
63 PlumaFileBrowserStore * model;
64 GCancellable * cancellable;
65 gboolean trash;
66 GList * files;
67 GList * iter;
68 gboolean removed;
69};
70
71struct _AsyncNode
72{
73 FileBrowserNodeDir *dir;
74 GCancellable *cancellable;
75 GSList *original_children;
76};
77
78typedef struct {
79 PlumaFileBrowserStore * model;
80 gchar * virtual_root;
81 GMountOperation * operation;
82 GCancellable * cancellable;
83} MountInfo;
84
85struct _FileBrowserNode
86{
87 GFile *file;
88 guint flags;
89 gchar *name;
90
91 GdkPixbuf *icon;
92 GdkPixbuf *emblem;
93
94 FileBrowserNode *parent;
95 gint pos;
96 gboolean inserted;
97};
98
99struct _FileBrowserNodeDir
100{
101 FileBrowserNode node;
102 GSList *children;
103
104 GCancellable *cancellable;
105 GFileMonitor *monitor;
106 PlumaFileBrowserStore *model;
107};
108
109struct _PlumaFileBrowserStorePrivate
110{
111 FileBrowserNode *root;
112 FileBrowserNode *virtual_root;
113 GType column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_NUM];
114
115 PlumaFileBrowserStoreFilterMode filter_mode;
116 PlumaFileBrowserStoreFilterFunc filter_func;
117 gpointer filter_user_data;
118
119 SortFunc sort_func;
120
121 GSList *async_handles;
122 MountInfo *mount_info;
123};
124
125static FileBrowserNode *model_find_node (PlumaFileBrowserStore *model,
126 FileBrowserNode *node,
127 GFile *uri);
128static void model_remove_node (PlumaFileBrowserStore * model,
129 FileBrowserNode * node,
130 GtkTreePath * path,
131 gboolean free_nodes);
132
133static void set_virtual_root_from_node (PlumaFileBrowserStore * model,
134 FileBrowserNode * node);
135
136static void pluma_file_browser_store_iface_init (GtkTreeModelIface * iface);
137static GtkTreeModelFlags pluma_file_browser_store_get_flags (GtkTreeModel * tree_model);
138static gint pluma_file_browser_store_get_n_columns (GtkTreeModel * tree_model);
139static GType pluma_file_browser_store_get_column_type (GtkTreeModel * tree_model,
140 gint index);
141static gboolean pluma_file_browser_store_get_iter (GtkTreeModel * tree_model,
142 GtkTreeIter * iter,
143 GtkTreePath * path);
144static GtkTreePath *pluma_file_browser_store_get_path (GtkTreeModel * tree_model,
145 GtkTreeIter * iter);
146static void pluma_file_browser_store_get_value (GtkTreeModel * tree_model,
147 GtkTreeIter * iter,
148 gint column,
149 GValue * value);
150static gboolean pluma_file_browser_store_iter_next (GtkTreeModel * tree_model,
151 GtkTreeIter * iter);
152static gboolean pluma_file_browser_store_iter_children (GtkTreeModel * tree_model,
153 GtkTreeIter * iter,
154 GtkTreeIter * parent);
155static gboolean pluma_file_browser_store_iter_has_child (GtkTreeModel * tree_model,
156 GtkTreeIter * iter);
157static gint pluma_file_browser_store_iter_n_children (GtkTreeModel * tree_model,
158 GtkTreeIter * iter);
159static gboolean pluma_file_browser_store_iter_nth_child (GtkTreeModel * tree_model,
160 GtkTreeIter * iter,
161 GtkTreeIter * parent,
162 gint n);
163static gboolean pluma_file_browser_store_iter_parent (GtkTreeModel * tree_model,
164 GtkTreeIter * iter,
165 GtkTreeIter * child);
166static void pluma_file_browser_store_row_inserted (GtkTreeModel * tree_model,
167 GtkTreePath * path,
168 GtkTreeIter * iter);
169
170static void pluma_file_browser_store_drag_source_init (GtkTreeDragSourceIface * iface);
171static gboolean pluma_file_browser_store_row_draggable (GtkTreeDragSource * drag_source,
172 GtkTreePath * path);
173static gboolean pluma_file_browser_store_drag_data_delete (GtkTreeDragSource * drag_source,
174 GtkTreePath * path);
175static gboolean pluma_file_browser_store_drag_data_get (GtkTreeDragSource * drag_source,
176 GtkTreePath * path,
177 GtkSelectionData * selection_data);
178
179static void file_browser_node_free (PlumaFileBrowserStore * model,
180 FileBrowserNode * node);
181static void model_add_node (PlumaFileBrowserStore * model,
182 FileBrowserNode * child,
183 FileBrowserNode * parent);
184static void model_clear (PlumaFileBrowserStore * model,
185 gboolean free_nodes);
186static gint model_sort_default (FileBrowserNode * node1,
187 FileBrowserNode * node2);
188static void model_check_dummy (PlumaFileBrowserStore * model,
189 FileBrowserNode * node);
190static void next_files_async (GFileEnumerator * enumerator,
191 AsyncNode * async);
192
193static void delete_files (AsyncData *data);
194
195G_DEFINE_DYNAMIC_TYPE_EXTENDED (PlumaFileBrowserStore, pluma_file_browser_store,static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
196 G_TYPE_OBJECT,static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
197 0,static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
198 G_ADD_PRIVATE_DYNAMIC (PlumaFileBrowserStore)static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
199 G_IMPLEMENT_INTERFACE_DYNAMIC (GTK_TYPE_TREE_MODEL,static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
200 pluma_file_browser_store_iface_init)static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
201 G_IMPLEMENT_INTERFACE_DYNAMIC (GTK_TYPE_TREE_DRAG_SOURCE,static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
202 pluma_file_browser_store_drag_source_init))static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
203
204/* Properties */
205enum {
206 PROP_0,
207
208 PROP_ROOT,
209 PROP_VIRTUAL_ROOT,
210 PROP_FILTER_MODE
211};
212
213/* Signals */
214enum
215{
216 BEGIN_LOADING,
217 END_LOADING,
218 ERROR,
219 NO_TRASH,
220 RENAME,
221 BEGIN_REFRESH,
222 END_REFRESH,
223 UNLOAD,
224 NUM_SIGNALS
225};
226
227static guint model_signals[NUM_SIGNALS] = { 0 };
228
229static void
230cancel_mount_operation (PlumaFileBrowserStore *obj)
231{
232 if (obj->priv->mount_info != NULL((void*)0))
233 {
234 obj->priv->mount_info->model = NULL((void*)0);
235 g_cancellable_cancel (obj->priv->mount_info->cancellable);
236 obj->priv->mount_info = NULL((void*)0);
237 }
238}
239
240static void
241pluma_file_browser_store_finalize (GObject * object)
242{
243 PlumaFileBrowserStore *obj = PLUMA_FILE_BROWSER_STORE (object)((((PlumaFileBrowserStore*) (void *) ((object)))));
244 GSList *item;
245
246 /* Free all the nodes */
247 file_browser_node_free (obj, obj->priv->root);
248
249 /* Cancel any asynchronous operations */
250 for (item = obj->priv->async_handles; item; item = item->next)
251 {
252 AsyncData *data = (AsyncData *) (item->data);
253 g_cancellable_cancel (data->cancellable);
254
255 data->removed = TRUE(!(0));
256 }
257
258 cancel_mount_operation (obj);
259
260 g_slist_free (obj->priv->async_handles);
261 G_OBJECT_CLASS (pluma_file_browser_store_parent_class)((((GObjectClass*) (void *) ((pluma_file_browser_store_parent_class
)))))
->finalize (object);
262}
263
264static void
265set_gvalue_from_node (GValue *value,
266 FileBrowserNode *node)
267{
268 gchar * uri;
269
270 if (node == NULL((void*)0) || !node->file) {
271 g_value_set_string (value, NULL((void*)0));
272 } else {
273 uri = g_file_get_uri (node->file);
274 g_value_take_string (value, uri);
275 }
276}
277
278static void
279pluma_file_browser_store_get_property (GObject *object,
280 guint prop_id,
281 GValue *value,
282 GParamSpec *pspec)
283{
284 PlumaFileBrowserStore *obj = PLUMA_FILE_BROWSER_STORE (object)((((PlumaFileBrowserStore*) (void *) ((object)))));
285
286 switch (prop_id)
287 {
288 case PROP_ROOT:
289 set_gvalue_from_node (value, obj->priv->root);
290 break;
291 case PROP_VIRTUAL_ROOT:
292 set_gvalue_from_node (value, obj->priv->virtual_root);
293 break;
294 case PROP_FILTER_MODE:
295 g_value_set_flags (value, obj->priv->filter_mode);
296 break;
297 default:
298 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "pluma-file-browser-store.c", 298, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
299 break;
300 }
301}
302
303static void
304pluma_file_browser_store_set_property (GObject *object,
305 guint prop_id,
306 const GValue *value,
307 GParamSpec *pspec)
308{
309 PlumaFileBrowserStore *obj = PLUMA_FILE_BROWSER_STORE (object)((((PlumaFileBrowserStore*) (void *) ((object)))));
310
311 switch (prop_id)
312 {
313 case PROP_FILTER_MODE:
314 pluma_file_browser_store_set_filter_mode (obj,
315 g_value_get_flags (value));
316 break;
317 default:
318 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "pluma-file-browser-store.c", 318, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
319 break;
320 }
321}
322
323static void
324pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass * klass)
325{
326 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) ((klass)))));
327
328 object_class->finalize = pluma_file_browser_store_finalize;
329
330 object_class->get_property = pluma_file_browser_store_get_property;
331 object_class->set_property = pluma_file_browser_store_set_property;
332
333 g_object_class_install_property (object_class, PROP_ROOT,
334 g_param_spec_string ("root",
335 "Root",
336 "The root uri",
337 NULL((void*)0),
338 G_PARAM_READABLE));
339
340 g_object_class_install_property (object_class, PROP_VIRTUAL_ROOT,
341 g_param_spec_string ("virtual-root",
342 "Virtual Root",
343 "The virtual root uri",
344 NULL((void*)0),
345 G_PARAM_READABLE));
346
347 g_object_class_install_property (object_class, PROP_FILTER_MODE,
348 g_param_spec_flags ("filter-mode",
349 "Filter Mode",
350 "The filter mode",
351 PLUMA_TYPE_FILE_BROWSER_STORE_FILTER_MODE(pluma_file_browser_store_filter_mode_get_type()),
352 pluma_file_browser_store_filter_mode_get_default (),
353 G_PARAM_READWRITE));
354
355 model_signals[BEGIN_LOADING] =
356 g_signal_new ("begin-loading",
357 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
358 G_SIGNAL_RUN_LAST,
359 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, begin_loading)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, begin_loading
))
,
360 NULL((void*)0), NULL((void*)0), NULL((void*)0),
361 G_TYPE_NONE((GType) ((1) << (2))), 1, GTK_TYPE_TREE_ITER(gtk_tree_iter_get_type ()));
362 model_signals[END_LOADING] =
363 g_signal_new ("end-loading",
364 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
365 G_SIGNAL_RUN_LAST,
366 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, end_loading)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, end_loading
))
,
367 NULL((void*)0), NULL((void*)0), NULL((void*)0),
368 G_TYPE_NONE((GType) ((1) << (2))), 1,
369 GTK_TYPE_TREE_ITER(gtk_tree_iter_get_type ()));
370 model_signals[ERROR] =
371 g_signal_new ("error", G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
372 G_SIGNAL_RUN_LAST,
373 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, error)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, error
))
,
374 NULL((void*)0), NULL((void*)0), NULL((void*)0),
375 G_TYPE_NONE((GType) ((1) << (2))), 2, G_TYPE_UINT((GType) ((7) << (2))), G_TYPE_STRING((GType) ((16) << (2))));
376 model_signals[NO_TRASH] =
377 g_signal_new ("no-trash", G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
378 G_SIGNAL_RUN_LAST,
379 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, no_trash)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, no_trash
))
,
380 g_signal_accumulator_true_handled, NULL((void*)0), NULL((void*)0),
381 G_TYPE_BOOLEAN((GType) ((5) << (2))), 1, G_TYPE_POINTER((GType) ((17) << (2))));
382 model_signals[RENAME] =
383 g_signal_new ("rename",
384 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
385 G_SIGNAL_RUN_LAST,
386 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, rename)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, rename
))
,
387 NULL((void*)0), NULL((void*)0), NULL((void*)0),
388 G_TYPE_NONE((GType) ((1) << (2))), 2,
389 G_TYPE_STRING((GType) ((16) << (2))),
390 G_TYPE_STRING((GType) ((16) << (2))));
391 model_signals[BEGIN_REFRESH] =
392 g_signal_new ("begin-refresh",
393 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
394 G_SIGNAL_RUN_LAST,
395 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, begin_refresh)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, begin_refresh
))
,
396 NULL((void*)0), NULL((void*)0), NULL((void*)0),
397 G_TYPE_NONE((GType) ((1) << (2))), 0);
398 model_signals[END_REFRESH] =
399 g_signal_new ("end-refresh",
400 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
401 G_SIGNAL_RUN_LAST,
402 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, end_refresh)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, end_refresh
))
,
403 NULL((void*)0), NULL((void*)0), NULL((void*)0),
404 G_TYPE_NONE((GType) ((1) << (2))), 0);
405 model_signals[UNLOAD] =
406 g_signal_new ("unload",
407 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
408 G_SIGNAL_RUN_LAST,
409 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, unload)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, unload
))
,
410 NULL((void*)0), NULL((void*)0), NULL((void*)0),
411 G_TYPE_NONE((GType) ((1) << (2))), 1,
412 G_TYPE_STRING((GType) ((16) << (2))));
413}
414
415static void
416pluma_file_browser_store_class_finalize (PlumaFileBrowserStoreClass *klass)
417{
418 /* dummy function - used by G_DEFINE_DYNAMIC_TYPE_EXTENDED */
419}
420
421static void
422pluma_file_browser_store_iface_init (GtkTreeModelIface * iface)
423{
424 iface->get_flags = pluma_file_browser_store_get_flags;
425 iface->get_n_columns = pluma_file_browser_store_get_n_columns;
426 iface->get_column_type = pluma_file_browser_store_get_column_type;
427 iface->get_iter = pluma_file_browser_store_get_iter;
428 iface->get_path = pluma_file_browser_store_get_path;
429 iface->get_value = pluma_file_browser_store_get_value;
430 iface->iter_next = pluma_file_browser_store_iter_next;
431 iface->iter_children = pluma_file_browser_store_iter_children;
432 iface->iter_has_child = pluma_file_browser_store_iter_has_child;
433 iface->iter_n_children = pluma_file_browser_store_iter_n_children;
434 iface->iter_nth_child = pluma_file_browser_store_iter_nth_child;
435 iface->iter_parent = pluma_file_browser_store_iter_parent;
436 iface->row_inserted = pluma_file_browser_store_row_inserted;
437}
438
439static void
440pluma_file_browser_store_drag_source_init (GtkTreeDragSourceIface * iface)
441{
442 iface->row_draggable = pluma_file_browser_store_row_draggable;
443 iface->drag_data_delete = pluma_file_browser_store_drag_data_delete;
444 iface->drag_data_get = pluma_file_browser_store_drag_data_get;
445}
446
447static void
448pluma_file_browser_store_init (PlumaFileBrowserStore * obj)
449{
450 obj->priv = pluma_file_browser_store_get_instance_private (obj);
451
452 obj->priv->column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_URI] =
453 G_TYPE_STRING((GType) ((16) << (2)));
454 obj->priv->column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_NAME] =
455 G_TYPE_STRING((GType) ((16) << (2)));
456 obj->priv->column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_FLAGS] =
457 G_TYPE_UINT((GType) ((7) << (2)));
458 obj->priv->column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_ICON] =
459 GDK_TYPE_PIXBUF(gdk_pixbuf_get_type ());
460 obj->priv->column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM] =
461 GDK_TYPE_PIXBUF(gdk_pixbuf_get_type ());
462
463 // Default filter mode is hiding the hidden files
464 obj->priv->filter_mode = pluma_file_browser_store_filter_mode_get_default ();
465 obj->priv->sort_func = model_sort_default;
466}
467
468static gboolean
469node_has_parent (FileBrowserNode * node, FileBrowserNode * parent)
470{
471 if (node->parent == NULL((void*)0))
472 return FALSE(0);
473
474 if (node->parent == parent)
475 return TRUE(!(0));
476
477 return node_has_parent (node->parent, parent);
478}
479
480static gboolean
481node_in_tree (PlumaFileBrowserStore * model, FileBrowserNode * node)
482{
483 return node_has_parent (node, model->priv->virtual_root);
484}
485
486static gboolean
487model_node_visibility (PlumaFileBrowserStore * model,
488 FileBrowserNode * node)
489{
490 if (node == NULL((void*)0))
491 return FALSE(0);
492
493 if (NODE_IS_DUMMY (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
)
494 return !NODE_IS_HIDDEN (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
))
;
495
496 if (node == model->priv->virtual_root)
497 return TRUE(!(0));
498
499 if (!node_has_parent (node, model->priv->virtual_root))
500 return FALSE(0);
501
502 return !NODE_IS_FILTERED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED
))
;
503}
504
505static gboolean
506model_node_inserted (PlumaFileBrowserStore * model,
507 FileBrowserNode * node)
508{
509 return node == model->priv->virtual_root || (model_node_visibility (model, node) && node->inserted);
510}
511
512/* Interface implementation */
513
514static GtkTreeModelFlags
515pluma_file_browser_store_get_flags (GtkTreeModel * tree_model)
516{
517 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_98
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_98 = 1; else _g_boolean_var_98 = 0
; _g_boolean_var_98; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((GtkTreeModelFlags) 0); } } while (0)
518 (GtkTreeModelFlags) 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_98
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_98 = 1; else _g_boolean_var_98 = 0
; _g_boolean_var_98; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((GtkTreeModelFlags) 0); } } while (0)
;
519
520 return GTK_TREE_MODEL_ITERS_PERSIST;
521}
522
523static gint
524pluma_file_browser_store_get_n_columns (GtkTreeModel * tree_model)
525{
526 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_99
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_99 = 1; else _g_boolean_var_99 = 0
; _g_boolean_var_99; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return (0); } } while (0)
;
527
528 return PLUMA_FILE_BROWSER_STORE_COLUMN_NUM;
529}
530
531static GType
532pluma_file_browser_store_get_column_type (GtkTreeModel * tree_model, gint idx)
533{
534 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_100
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_100 = 1; else _g_boolean_var_100 =
0; _g_boolean_var_100; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return (((GType) ((0) << (2)))); } } while (0)
535 G_TYPE_INVALID)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_100
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_100 = 1; else _g_boolean_var_100 =
0; _g_boolean_var_100; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return (((GType) ((0) << (2)))); } } while (0)
;
536 g_return_val_if_fail (idx < PLUMA_FILE_BROWSER_STORE_COLUMN_NUM &&do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_101
; if (idx < PLUMA_FILE_BROWSER_STORE_COLUMN_NUM &&
idx >= 0) _g_boolean_var_101 = 1; else _g_boolean_var_101
= 0; _g_boolean_var_101; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "idx < PLUMA_FILE_BROWSER_STORE_COLUMN_NUM && idx >= 0"
); return (((GType) ((0) << (2)))); } } while (0)
537 idx >= 0, G_TYPE_INVALID)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_101
; if (idx < PLUMA_FILE_BROWSER_STORE_COLUMN_NUM &&
idx >= 0) _g_boolean_var_101 = 1; else _g_boolean_var_101
= 0; _g_boolean_var_101; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "idx < PLUMA_FILE_BROWSER_STORE_COLUMN_NUM && idx >= 0"
); return (((GType) ((0) << (2)))); } } while (0)
;
538
539 return PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))))->priv->column_types[idx];
540}
541
542static gboolean
543pluma_file_browser_store_get_iter (GtkTreeModel * tree_model,
544 GtkTreeIter * iter, GtkTreePath * path)
545{
546 gint * indices, depth, i;
547 FileBrowserNode * node;
548 PlumaFileBrowserStore * model;
549 gint num;
550
551 g_assert (PLUMA_IS_FILE_BROWSER_STORE (tree_model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_102
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_102 = 1; else _g_boolean_var_102 =
0; _g_boolean_var_102; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "pluma-file-browser-store.c", 551, ((const char
*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"); }
while (0)
;
552 g_assert (path != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_103
; if (path != ((void*)0)) _g_boolean_var_103 = 1; else _g_boolean_var_103
= 0; _g_boolean_var_103; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "pluma-file-browser-store.c", 552, ((const char
*) (__func__)), "path != NULL"); } while (0)
;
553
554 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
555 indices = gtk_tree_path_get_indices (path);
556 depth = gtk_tree_path_get_depth (path);
557 node = model->priv->virtual_root;
558
559 for (i = 0; i < depth; ++i) {
560 GSList * item;
561
562 if (node == NULL((void*)0))
563 return FALSE(0);
564
565 num = 0;
566
567 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
568 return FALSE(0);
569
570 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item; item = item->next) {
571 FileBrowserNode * child;
572
573 child = (FileBrowserNode *) (item->data);
574
575 if (model_node_inserted (model, child)) {
576 if (num == indices[i]) {
577 node = child;
Value stored to 'node' is never read
578 break;
579 }
580
581 num++;
582 }
583 }
584
585 if (item == NULL((void*)0))
586 return FALSE(0);
587
588 node = (FileBrowserNode *) (item->data);
589 }
590
591 iter->user_data = node;
592 iter->user_data2 = NULL((void*)0);
593 iter->user_data3 = NULL((void*)0);
594
595 return node != NULL((void*)0);
596}
597
598static GtkTreePath *
599pluma_file_browser_store_get_path_real (PlumaFileBrowserStore * model,
600 FileBrowserNode * node)
601{
602 GtkTreePath *path;
603 gint num = 0;
604
605 path = gtk_tree_path_new ();
606
607 while (node != model->priv->virtual_root) {
608 GSList *item;
609
610 if (node->parent == NULL((void*)0)) {
611 gtk_tree_path_free (path);
612 return NULL((void*)0);
613 }
614
615 num = 0;
616
617 for (item = FILE_BROWSER_NODE_DIR (node->parent)((FileBrowserNodeDir *)(node->parent))->children; item; item = item->next) {
618 FileBrowserNode *check;
619
620 check = (FileBrowserNode *) (item->data);
621
622 if (model_node_visibility (model, check) && (check == node || check->inserted)) {
623 if (check == node) {
624 gtk_tree_path_prepend_index (path,
625 num);
626 break;
627 }
628
629 ++num;
630 } else if (check == node) {
631 if (NODE_IS_DUMMY (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
)
632 g_warning ("Dummy not visible???");
633
634 gtk_tree_path_free (path);
635 return NULL((void*)0);
636 }
637 }
638
639 node = node->parent;
640 }
641
642 return path;
643}
644
645static GtkTreePath *
646pluma_file_browser_store_get_path (GtkTreeModel * tree_model,
647 GtkTreeIter * iter)
648{
649 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_104
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_104 = 1; else _g_boolean_var_104 =
0; _g_boolean_var_104; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return (((void*)0)); } } while (0)
;
650 g_return_val_if_fail (iter != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_105
; if (iter != ((void*)0)) _g_boolean_var_105 = 1; else _g_boolean_var_105
= 0; _g_boolean_var_105; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
(((void*)0)); } } while (0)
;
651 g_return_val_if_fail (iter->user_data != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_106
; if (iter->user_data != ((void*)0)) _g_boolean_var_106 = 1
; else _g_boolean_var_106 = 0; _g_boolean_var_106; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return (((void
*)0)); } } while (0)
;
652
653 return pluma_file_browser_store_get_path_real (PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model))))),
654 (FileBrowserNode *) (iter->user_data));
655}
656
657static void
658pluma_file_browser_store_get_value (GtkTreeModel * tree_model,
659 GtkTreeIter * iter,
660 gint column,
661 GValue * value)
662{
663 FileBrowserNode *node;
664
665 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_107
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_107 = 1; else _g_boolean_var_107 =
0; _g_boolean_var_107; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return; } } while (0)
;
666 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_108
; if (iter != ((void*)0)) _g_boolean_var_108 = 1; else _g_boolean_var_108
= 0; _g_boolean_var_108; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
667 g_return_if_fail (iter->user_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_109
; if (iter->user_data != ((void*)0)) _g_boolean_var_109 = 1
; else _g_boolean_var_109 = 0; _g_boolean_var_109; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return; } } while
(0)
;
668
669 node = (FileBrowserNode *) (iter->user_data);
670
671 g_value_init (value, PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))))->priv->column_types[column]);
672
673 switch (column) {
674 case PLUMA_FILE_BROWSER_STORE_COLUMN_URI:
675 set_gvalue_from_node (value, node);
676 break;
677 case PLUMA_FILE_BROWSER_STORE_COLUMN_NAME:
678 g_value_set_string (value, node->name);
679 break;
680 case PLUMA_FILE_BROWSER_STORE_COLUMN_FLAGS:
681 g_value_set_uint (value, node->flags);
682 break;
683 case PLUMA_FILE_BROWSER_STORE_COLUMN_ICON:
684 g_value_set_object (value, node->icon);
685 break;
686 case PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM:
687 g_value_set_object (value, node->emblem);
688 break;
689 default:
690 g_return_if_reached ()do { g_log (((gchar*) 0), G_LOG_LEVEL_CRITICAL, "file %s: line %d (%s): should not be reached"
, "pluma-file-browser-store.c", 690, ((const char*) (__func__
))); return; } while (0)
;
691 }
692}
693
694static gboolean
695pluma_file_browser_store_iter_next (GtkTreeModel * tree_model,
696 GtkTreeIter * iter)
697{
698 PlumaFileBrowserStore * model;
699 FileBrowserNode * node;
700 GSList * item;
701 GSList * first;
702
703 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_110
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_110 = 1; else _g_boolean_var_110 =
0; _g_boolean_var_110; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
704 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_110
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_110 = 1; else _g_boolean_var_110 =
0; _g_boolean_var_110; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
705 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_111
; if (iter != ((void*)0)) _g_boolean_var_111 = 1; else _g_boolean_var_111
= 0; _g_boolean_var_111; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
706 g_return_val_if_fail (iter->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_112
; if (iter->user_data != ((void*)0)) _g_boolean_var_112 = 1
; else _g_boolean_var_112 = 0; _g_boolean_var_112; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return ((0)); }
} while (0)
;
707
708 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
709 node = (FileBrowserNode *) (iter->user_data);
710
711 if (node->parent == NULL((void*)0))
712 return FALSE(0);
713
714 first = g_slist_next (g_slist_find (FILE_BROWSER_NODE_DIR (node->parent)->children, node))((g_slist_find (((FileBrowserNodeDir *)(node->parent))->
children, node)) ? (((GSList *)(g_slist_find (((FileBrowserNodeDir
*)(node->parent))->children, node)))->next) : ((void
*)0))
;
715
716 for (item = first; item; item = item->next) {
717 if (model_node_inserted (model, (FileBrowserNode *) (item->data))) {
718 iter->user_data = item->data;
719 return TRUE(!(0));
720 }
721 }
722
723 return FALSE(0);
724}
725
726static gboolean
727pluma_file_browser_store_iter_children (GtkTreeModel * tree_model,
728 GtkTreeIter * iter,
729 GtkTreeIter * parent)
730{
731 FileBrowserNode * node;
732 PlumaFileBrowserStore * model;
733 GSList * item;
734
735 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_113
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_113 = 1; else _g_boolean_var_113 =
0; _g_boolean_var_113; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
736 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_113
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_113 = 1; else _g_boolean_var_113 =
0; _g_boolean_var_113; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
737 g_return_val_if_fail (parent == NULLdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_114
; if (parent == ((void*)0) || parent->user_data != ((void*
)0)) _g_boolean_var_114 = 1; else _g_boolean_var_114 = 0; _g_boolean_var_114
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "parent == NULL || parent->user_data != NULL"
); return ((0)); } } while (0)
738 || parent->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_114
; if (parent == ((void*)0) || parent->user_data != ((void*
)0)) _g_boolean_var_114 = 1; else _g_boolean_var_114 = 0; _g_boolean_var_114
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "parent == NULL || parent->user_data != NULL"
); return ((0)); } } while (0)
;
739
740 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
741
742 if (parent == NULL((void*)0))
743 node = model->priv->virtual_root;
744 else
745 node = (FileBrowserNode *) (parent->user_data);
746
747 if (node == NULL((void*)0))
748 return FALSE(0);
749
750 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
751 return FALSE(0);
752
753 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item; item = item->next) {
754 if (model_node_inserted (model, (FileBrowserNode *) (item->data))) {
755 iter->user_data = item->data;
756 return TRUE(!(0));
757 }
758 }
759
760 return FALSE(0);
761}
762
763static gboolean
764filter_tree_model_iter_has_child_real (PlumaFileBrowserStore * model,
765 FileBrowserNode * node)
766{
767 GSList *item;
768
769 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
770 return FALSE(0);
771
772 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item; item = item->next) {
773 if (model_node_inserted (model, (FileBrowserNode *) (item->data)))
774 return TRUE(!(0));
775 }
776
777 return FALSE(0);
778}
779
780static gboolean
781pluma_file_browser_store_iter_has_child (GtkTreeModel * tree_model,
782 GtkTreeIter * iter)
783{
784 FileBrowserNode *node;
785 PlumaFileBrowserStore *model;
786
787 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_115
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_115 = 1; else _g_boolean_var_115 =
0; _g_boolean_var_115; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
788 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_115
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_115 = 1; else _g_boolean_var_115 =
0; _g_boolean_var_115; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
789 g_return_val_if_fail (iter == NULLdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_116
; if (iter == ((void*)0) || iter->user_data != ((void*)0))
_g_boolean_var_116 = 1; else _g_boolean_var_116 = 0; _g_boolean_var_116
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "iter == NULL || iter->user_data != NULL"
); return ((0)); } } while (0)
790 || iter->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_116
; if (iter == ((void*)0) || iter->user_data != ((void*)0))
_g_boolean_var_116 = 1; else _g_boolean_var_116 = 0; _g_boolean_var_116
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "iter == NULL || iter->user_data != NULL"
); return ((0)); } } while (0)
;
791
792 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
793
794 if (iter == NULL((void*)0))
795 node = model->priv->virtual_root;
796 else
797 node = (FileBrowserNode *) (iter->user_data);
798
799 return filter_tree_model_iter_has_child_real (model, node);
800}
801
802static gint
803pluma_file_browser_store_iter_n_children (GtkTreeModel * tree_model,
804 GtkTreeIter * iter)
805{
806 FileBrowserNode *node;
807 PlumaFileBrowserStore *model;
808 GSList *item;
809 gint num = 0;
810
811 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_117
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_117 = 1; else _g_boolean_var_117 =
0; _g_boolean_var_117; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
812 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_117
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_117 = 1; else _g_boolean_var_117 =
0; _g_boolean_var_117; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
813 g_return_val_if_fail (iter == NULLdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_118
; if (iter == ((void*)0) || iter->user_data != ((void*)0))
_g_boolean_var_118 = 1; else _g_boolean_var_118 = 0; _g_boolean_var_118
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "iter == NULL || iter->user_data != NULL"
); return ((0)); } } while (0)
814 || iter->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_118
; if (iter == ((void*)0) || iter->user_data != ((void*)0))
_g_boolean_var_118 = 1; else _g_boolean_var_118 = 0; _g_boolean_var_118
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "iter == NULL || iter->user_data != NULL"
); return ((0)); } } while (0)
;
815
816 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
817
818 if (iter == NULL((void*)0))
819 node = model->priv->virtual_root;
820 else
821 node = (FileBrowserNode *) (iter->user_data);
822
823 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
824 return 0;
825
826 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item; item = item->next)
827 if (model_node_inserted (model, (FileBrowserNode *) (item->data)))
828 ++num;
829
830 return num;
831}
832
833static gboolean
834pluma_file_browser_store_iter_nth_child (GtkTreeModel * tree_model,
835 GtkTreeIter * iter,
836 GtkTreeIter * parent, gint n)
837{
838 FileBrowserNode *node;
839 PlumaFileBrowserStore *model;
840 GSList *item;
841 gint num = 0;
842
843 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_119
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_119 = 1; else _g_boolean_var_119 =
0; _g_boolean_var_119; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
844 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_119
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_119 = 1; else _g_boolean_var_119 =
0; _g_boolean_var_119; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
845 g_return_val_if_fail (parent == NULLdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_120
; if (parent == ((void*)0) || parent->user_data != ((void*
)0)) _g_boolean_var_120 = 1; else _g_boolean_var_120 = 0; _g_boolean_var_120
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "parent == NULL || parent->user_data != NULL"
); return ((0)); } } while (0)
846 || parent->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_120
; if (parent == ((void*)0) || parent->user_data != ((void*
)0)) _g_boolean_var_120 = 1; else _g_boolean_var_120 = 0; _g_boolean_var_120
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "parent == NULL || parent->user_data != NULL"
); return ((0)); } } while (0)
;
847
848 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
849
850 if (parent == NULL((void*)0))
851 node = model->priv->virtual_root;
852 else
853 node = (FileBrowserNode *) (parent->user_data);
854
855 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
856 return FALSE(0);
857
858 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item;
859 item = item->next) {
860 if (model_node_inserted (model, (FileBrowserNode *) (item->data))) {
861 if (num == n) {
862 iter->user_data = item->data;
863 return TRUE(!(0));
864 }
865
866 ++num;
867 }
868 }
869
870 return FALSE(0);
871}
872
873static gboolean
874pluma_file_browser_store_iter_parent (GtkTreeModel * tree_model,
875 GtkTreeIter * iter,
876 GtkTreeIter * child)
877{
878 FileBrowserNode *node;
879 PlumaFileBrowserStore *model;
880
881 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_121
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_121 = 1; else _g_boolean_var_121 =
0; _g_boolean_var_121; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
882 g_return_val_if_fail (child != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_122
; if (child != ((void*)0)) _g_boolean_var_122 = 1; else _g_boolean_var_122
= 0; _g_boolean_var_122; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "child != NULL");
return ((0)); } } while (0)
;
883 g_return_val_if_fail (child->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_123
; if (child->user_data != ((void*)0)) _g_boolean_var_123 =
1; else _g_boolean_var_123 = 0; _g_boolean_var_123; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "child->user_data != NULL"); return ((0));
} } while (0)
;
884
885 node = (FileBrowserNode *) (child->user_data);
886 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
887
888 if (!node_in_tree (model, node))
889 return FALSE(0);
890
891 if (node->parent == NULL((void*)0))
892 return FALSE(0);
893
894 iter->user_data = node->parent;
895 return TRUE(!(0));
896}
897
898static void
899pluma_file_browser_store_row_inserted (GtkTreeModel * tree_model,
900 GtkTreePath * path,
901 GtkTreeIter * iter)
902{
903 FileBrowserNode * node = (FileBrowserNode *)(iter->user_data);
904
905 node->inserted = TRUE(!(0));
906}
907
908static gboolean
909pluma_file_browser_store_row_draggable (GtkTreeDragSource * drag_source,
910 GtkTreePath * path)
911{
912 GtkTreeIter iter;
913 PlumaFileBrowserStoreFlag flags;
914
915 if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source)((((GtkTreeModel*) (void *) ((drag_source))))),
916 &iter, path))
917 {
918 return FALSE(0);
919 }
920
921 gtk_tree_model_get (GTK_TREE_MODEL (drag_source)((((GtkTreeModel*) (void *) ((drag_source))))), &iter,
922 PLUMA_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
923 -1);
924
925 return !FILE_IS_DUMMY(flags)(flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY);
926}
927
928static gboolean
929pluma_file_browser_store_drag_data_delete (GtkTreeDragSource * drag_source,
930 GtkTreePath * path)
931{
932 return FALSE(0);
933}
934
935static gboolean
936pluma_file_browser_store_drag_data_get (GtkTreeDragSource * drag_source,
937 GtkTreePath * path,
938 GtkSelectionData * selection_data)
939{
940 GtkTreeIter iter;
941 gchar *uri;
942 gchar *uris[2] = {0, };
943 gboolean ret;
944
945 if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source)((((GtkTreeModel*) (void *) ((drag_source))))),
946 &iter, path))
947 {
948 return FALSE(0);
949 }
950
951 gtk_tree_model_get (GTK_TREE_MODEL (drag_source)((((GtkTreeModel*) (void *) ((drag_source))))), &iter,
952 PLUMA_FILE_BROWSER_STORE_COLUMN_URI, &uri,
953 -1);
954
955 g_assert (uri)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_124
; if (uri) _g_boolean_var_124 = 1; else _g_boolean_var_124 = 0
; _g_boolean_var_124; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "pluma-file-browser-store.c", 955, ((const char
*) (__func__)), "uri"); } while (0)
;
956
957 uris[0] = uri;
958 ret = gtk_selection_data_set_uris (selection_data, uris);
959
960 g_free (uri);
961
962 return ret;
963}
964
965#define FILTER_HIDDEN(mode)(mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_HIDDEN) (mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_HIDDEN)
966#define FILTER_BINARY(mode)(mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_BINARY) (mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_BINARY)
967
968/* Private */
969static void
970model_begin_loading (PlumaFileBrowserStore * model, FileBrowserNode * node)
971{
972 GtkTreeIter iter;
973
974 iter.user_data = node;
975 g_signal_emit (model, model_signals[BEGIN_LOADING], 0, &iter);
976}
977
978static void
979model_end_loading (PlumaFileBrowserStore * model, FileBrowserNode * node)
980{
981 GtkTreeIter iter;
982
983 iter.user_data = node;
984 g_signal_emit (model, model_signals[END_LOADING], 0, &iter);
985}
986
987static void
988model_node_update_visibility (PlumaFileBrowserStore * model,
989 FileBrowserNode * node)
990{
991 GtkTreeIter iter;
992
993 node->flags &= ~PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED;
994
995 if (FILTER_HIDDEN (model->priv->filter_mode)(model->priv->filter_mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_HIDDEN
)
&&
996 NODE_IS_HIDDEN (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
))
)
997 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED;
998 else if (FILTER_BINARY (model->priv->filter_mode)(model->priv->filter_mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_BINARY
)
&&
999 (!NODE_IS_TEXT (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_TEXT
))
&& !NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
))
1000 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED;
1001 else if (model->priv->filter_func) {
1002 iter.user_data = node;
1003
1004 if (!model->priv->
1005 filter_func (model, &iter,
1006 model->priv->filter_user_data))
1007 node->flags |=
1008 PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED;
1009 }
1010}
1011
1012static gint
1013collate_nodes (FileBrowserNode * node1, FileBrowserNode * node2)
1014{
1015 if (node1->name == NULL((void*)0))
1016 return -1;
1017 else if (node2->name == NULL((void*)0))
1018 return 1;
1019 else {
1020 gchar *k1, *k2;
1021 gint result;
1022
1023 k1 = g_utf8_collate_key_for_filename (node1->name, -1);
1024 k2 = g_utf8_collate_key_for_filename (node2->name, -1);
1025
1026 result = strcmp (k1, k2);
1027
1028 g_free (k1);
1029 g_free (k2);
1030
1031 return result;
1032 }
1033}
1034
1035static gint
1036model_sort_default (FileBrowserNode * node1, FileBrowserNode * node2)
1037{
1038 gint f1;
1039 gint f2;
1040
1041 f1 = NODE_IS_DUMMY (node1)(((node1)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
;
1042 f2 = NODE_IS_DUMMY (node2)(((node2)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
;
1043
1044 if (f1 && f2)
1045 {
1046 return 0;
1047 }
1048 else if (f1 || f2)
1049 {
1050 return f1 ? -1 : 1;
1051 }
1052
1053 f1 = NODE_IS_DIR (node1)(((node1)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
;
1054 f2 = NODE_IS_DIR (node2)(((node2)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
;
1055
1056 if (f1 != f2)
1057 {
1058 return f1 ? -1 : 1;
1059 }
1060
1061 f1 = NODE_IS_HIDDEN (node1)(((node1)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
))
;
1062 f2 = NODE_IS_HIDDEN (node2)(((node2)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
))
;
1063
1064 if (f1 != f2)
1065 {
1066 return f2 ? -1 : 1;
1067 }
1068
1069 return collate_nodes (node1, node2);
1070}
1071
1072static void
1073model_resort_node (PlumaFileBrowserStore * model, FileBrowserNode * node)
1074{
1075 FileBrowserNodeDir *dir;
1076 GSList *item;
1077 FileBrowserNode *child;
1078 gint pos = 0;
1079 GtkTreeIter iter;
1080 GtkTreePath *path;
1081 gint *neworder;
1082
1083 dir = FILE_BROWSER_NODE_DIR (node->parent)((FileBrowserNodeDir *)(node->parent));
1084
1085 if (!model_node_visibility (model, node->parent)) {
1086 /* Just sort the children of the parent */
1087 dir->children = g_slist_sort (dir->children,
1088 (GCompareFunc) (model->priv->
1089 sort_func));
1090 } else {
1091 /* Store current positions */
1092 for (item = dir->children; item; item = item->next) {
1093 child = (FileBrowserNode *) (item->data);
1094
1095 if (model_node_visibility (model, child))
1096 child->pos = pos++;
1097 }
1098
1099 dir->children = g_slist_sort (dir->children,
1100 (GCompareFunc) (model->priv->
1101 sort_func));
1102 neworder = g_new (gint, pos)(gint *) (__extension__ ({ gsize __n = (gsize) (pos); gsize __s
= sizeof (gint); gpointer __p; if (__s == 1) __p = g_malloc (
__n); else if (__builtin_constant_p (__n) && (__s == 0
|| __n <= (9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc
(__n * __s); else __p = g_malloc_n (__n, __s); __p; }))
;
1103 pos = 0;
1104
1105 /* Store the new positions */
1106 for (item = dir->children; item; item = item->next) {
1107 child = (FileBrowserNode *) (item->data);
1108
1109 if (model_node_visibility (model, child))
1110 neworder[pos++] = child->pos;
1111 }
1112
1113 iter.user_data = node->parent;
1114 path =
1115 pluma_file_browser_store_get_path_real (model,
1116 node->parent);
1117
1118 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (model)((((GtkTreeModel*) (void *) ((model))))),
1119 path, &iter, neworder);
1120
1121 g_free (neworder);
1122 gtk_tree_path_free (path);
1123 }
1124}
1125
1126static void
1127row_changed (PlumaFileBrowserStore * model,
1128 GtkTreePath ** path,
1129 GtkTreeIter * iter)
1130{
1131 GtkTreeRowReference *ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (model)((((GtkTreeModel*) (void *) ((model))))), *path);
1132
1133 /* Insert a copy of the actual path here because the row-inserted
1134 signal may alter the path */
1135 gtk_tree_model_row_changed (GTK_TREE_MODEL(model)((((GtkTreeModel*) (void *) ((model))))), *path, iter);
1136 gtk_tree_path_free (*path);
1137
1138 *path = gtk_tree_row_reference_get_path (ref);
1139 gtk_tree_row_reference_free (ref);
1140}
1141
1142static void
1143row_inserted (PlumaFileBrowserStore * model,
1144 GtkTreePath ** path,
1145 GtkTreeIter * iter)
1146{
1147 /* This function creates a row reference for the path because it's
1148 uncertain what might change the actual model/view when we insert
1149 a node, maybe another directory load is triggered for example.
1150 Because functions that use this function rely on the notion that
1151 the path remains pointed towards the inserted node, we use the
1152 reference to keep track. */
1153 GtkTreeRowReference *ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (model)((((GtkTreeModel*) (void *) ((model))))), *path);
1154 GtkTreePath * copy = gtk_tree_path_copy (*path);
1155
1156 gtk_tree_model_row_inserted (GTK_TREE_MODEL(model)((((GtkTreeModel*) (void *) ((model))))), copy, iter);
1157 gtk_tree_path_free (copy);
1158
1159 if (ref)
1160 {
1161 gtk_tree_path_free (*path);
1162
1163 /* To restore the path, we get the path from the reference. But, since
1164 we inserted a row, the path will be one index further than the
1165 actual path of our node. We therefore call gtk_tree_path_prev */
1166 *path = gtk_tree_row_reference_get_path (ref);
1167 gtk_tree_path_prev (*path);
1168 }
1169
1170 gtk_tree_row_reference_free (ref);
1171}
1172
1173static void
1174row_deleted (PlumaFileBrowserStore * model,
1175 const GtkTreePath * path)
1176{
1177 GtkTreePath *copy = gtk_tree_path_copy (path);
1178
1179 /* Delete a copy of the actual path here because the row-deleted
1180 signal may alter the path */
1181 gtk_tree_model_row_deleted (GTK_TREE_MODEL(model)((((GtkTreeModel*) (void *) ((model))))), copy);
1182 gtk_tree_path_free (copy);
1183}
1184
1185static void
1186model_refilter_node (PlumaFileBrowserStore * model,
1187 FileBrowserNode * node,
1188 GtkTreePath ** path)
1189{
1190 gboolean old_visible;
1191 gboolean new_visible;
1192 FileBrowserNodeDir *dir;
1193 GSList *item;
1194 GtkTreeIter iter;
1195 GtkTreePath *tmppath = NULL((void*)0);
1196 gboolean in_tree;
1197
1198 if (node == NULL((void*)0))
1199 return;
1200
1201 old_visible = model_node_visibility (model, node);
1202 model_node_update_visibility (model, node);
1203
1204 in_tree = node_in_tree (model, node);
1205
1206 if (path == NULL((void*)0))
1207 {
1208 if (in_tree)
1209 tmppath = pluma_file_browser_store_get_path_real (model,
1210 node);
1211 else
1212 tmppath = gtk_tree_path_new_first ();
1213
1214 path = &tmppath;
1215 }
1216
1217 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
1218 if (in_tree)
1219 gtk_tree_path_down (*path);
1220
1221 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
1222
1223 for (item = dir->children; item; item = item->next) {
1224 model_refilter_node (model,
1225 (FileBrowserNode *) (item->data),
1226 path);
1227 }
1228
1229 if (in_tree)
1230 gtk_tree_path_up (*path);
1231 }
1232
1233 if (in_tree) {
1234 new_visible = model_node_visibility (model, node);
1235
1236 if (old_visible != new_visible) {
1237 if (old_visible) {
1238 node->inserted = FALSE(0);
1239 row_deleted (model, *path);
1240 } else {
1241 iter.user_data = node;
1242 row_inserted (model, path, &iter);
1243 gtk_tree_path_next (*path);
1244 }
1245 } else if (old_visible) {
1246 gtk_tree_path_next (*path);
1247 }
1248 }
1249
1250 model_check_dummy (model, node);
1251
1252 if (tmppath)
1253 gtk_tree_path_free (tmppath);
1254}
1255
1256static void
1257model_refilter (PlumaFileBrowserStore * model)
1258{
1259 model_refilter_node (model, model->priv->root, NULL((void*)0));
1260}
1261
1262static void
1263file_browser_node_set_name (FileBrowserNode * node)
1264{
1265 g_free (node->name);
1266
1267 if (node->file) {
1268 node->name = pluma_file_browser_utils_file_basename (node->file);
1269 } else {
1270 node->name = NULL((void*)0);
1271 }
1272}
1273
1274static void
1275file_browser_node_init (FileBrowserNode * node, GFile * file,
1276 FileBrowserNode * parent)
1277{
1278 if (file != NULL((void*)0)) {
1279 node->file = g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
1280 file_browser_node_set_name (node);
1281 }
1282
1283 node->parent = parent;
1284}
1285
1286static FileBrowserNode *
1287file_browser_node_new (GFile * file, FileBrowserNode * parent)
1288{
1289 FileBrowserNode *node = g_slice_new0 (FileBrowserNode)(FileBrowserNode *) (__extension__ ({ gsize __s = sizeof (FileBrowserNode
); gpointer __p; __p = g_slice_alloc (__s); memset (__p, 0, __s
); __p; }))
;
1290
1291 file_browser_node_init (node, file, parent);
1292 return node;
1293}
1294
1295static FileBrowserNode *
1296file_browser_node_dir_new (PlumaFileBrowserStore * model,
1297 GFile * file, FileBrowserNode * parent)
1298{
1299 FileBrowserNode *node =
1300 (FileBrowserNode *) g_slice_new0 (FileBrowserNodeDir)(FileBrowserNodeDir *) (__extension__ ({ gsize __s = sizeof (
FileBrowserNodeDir); gpointer __p; __p = g_slice_alloc (__s);
memset (__p, 0, __s); __p; }))
;
1301
1302 file_browser_node_init (node, file, parent);
1303
1304 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY;
1305
1306 FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->model = model;
1307
1308 return node;
1309}
1310
1311static void
1312file_browser_node_free_children (PlumaFileBrowserStore * model,
1313 FileBrowserNode * node)
1314{
1315 GSList *item;
1316
1317 if (node == NULL((void*)0))
1318 return;
1319
1320 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
1321 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item;
1322 item = item->next)
1323 file_browser_node_free (model,
1324 (FileBrowserNode *) (item->
1325 data));
1326
1327 g_slist_free (FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children);
1328 FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children = NULL((void*)0);
1329
1330 /* This node is no longer loaded */
1331 node->flags &= ~PLUMA_FILE_BROWSER_STORE_FLAG_LOADED;
1332 }
1333}
1334
1335static void
1336file_browser_node_free (PlumaFileBrowserStore * model,
1337 FileBrowserNode * node)
1338{
1339 gchar *uri;
1340
1341 if (node == NULL((void*)0))
1342 return;
1343
1344 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
1345 {
1346 FileBrowserNodeDir *dir;
1347
1348 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
1349
1350 if (dir->cancellable) {
1351 g_cancellable_cancel (dir->cancellable);
1352 g_object_unref (dir->cancellable);
1353
1354 model_end_loading (model, node);
1355 }
1356
1357 file_browser_node_free_children (model, node);
1358
1359 if (dir->monitor) {
1360 g_file_monitor_cancel (dir->monitor);
1361 g_object_unref (dir->monitor);
1362 }
1363 }
1364
1365 if (node->file)
1366 {
1367 uri = g_file_get_uri (node->file);
1368 g_signal_emit (model, model_signals[UNLOAD], 0, uri);
1369
1370 g_free (uri);
1371 g_object_unref (node->file);
1372 }
1373
1374 if (node->icon)
1375 g_object_unref (node->icon);
1376
1377 if (node->emblem)
1378 g_object_unref (node->emblem);
1379
1380 g_free (node->name);
1381
1382 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
1383 g_slice_free (FileBrowserNodeDir, (FileBrowserNodeDir *)node)do { if (1) g_slice_free1 (sizeof (FileBrowserNodeDir), ((FileBrowserNodeDir
*)node)); else (void) ((FileBrowserNodeDir*) 0 == ((FileBrowserNodeDir
*)node)); } while (0)
;
1384 else
1385 g_slice_free (FileBrowserNode, (FileBrowserNode *)node)do { if (1) g_slice_free1 (sizeof (FileBrowserNode), ((FileBrowserNode
*)node)); else (void) ((FileBrowserNode*) 0 == ((FileBrowserNode
*)node)); } while (0)
;
1386}
1387
1388/**
1389 * model_remove_node_children:
1390 * @model: the #PlumaFileBrowserStore
1391 * @node: the FileBrowserNode to remove
1392 * @path: the path of the node, or NULL to let the path be calculated
1393 * @free_nodes: whether to also remove the nodes from memory
1394 *
1395 * Removes all the children of node from the model. This function is used
1396 * to remove the child nodes from the _model_. Don't use it to just free
1397 * a node.
1398 **/
1399static void
1400model_remove_node_children (PlumaFileBrowserStore * model,
1401 FileBrowserNode * node,
1402 GtkTreePath * path,
1403 gboolean free_nodes)
1404{
1405 FileBrowserNodeDir *dir;
1406 GtkTreePath *path_child;
1407 GSList *list;
1408 GSList *item;
1409
1410 if (node == NULL((void*)0) || !NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
1411 return;
1412
1413 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
1414
1415 if (dir->children == NULL((void*)0))
1416 return;
1417
1418 if (!model_node_visibility (model, node)) {
1419 // Node is invisible and therefore the children can just
1420 // be freed
1421 if (free_nodes)
1422 file_browser_node_free_children (model, node);
1423
1424 return;
1425 }
1426
1427 if (path == NULL((void*)0))
1428 path_child =
1429 pluma_file_browser_store_get_path_real (model, node);
1430 else
1431 path_child = gtk_tree_path_copy (path);
1432
1433 gtk_tree_path_down (path_child);
1434
1435 list = g_slist_copy (dir->children);
1436
1437 for (item = list; item; item = item->next) {
1438 model_remove_node (model, (FileBrowserNode *) (item->data),
1439 path_child, free_nodes);
1440 }
1441
1442 g_slist_free (list);
1443 gtk_tree_path_free (path_child);
1444}
1445
1446/**
1447 * model_remove_node:
1448 * @model: the #PlumaFileBrowserStore
1449 * @node: the FileBrowserNode to remove
1450 * @path: the path to use to remove this node, or NULL to use the path
1451 * calculated from the node itself
1452 * @free_nodes: whether to also remove the nodes from memory
1453 *
1454 * Removes this node and all its children from the model. This function is used
1455 * to remove the node from the _model_. Don't use it to just free
1456 * a node.
1457 **/
1458static void
1459model_remove_node (PlumaFileBrowserStore * model,
1460 FileBrowserNode * node,
1461 GtkTreePath * path,
1462 gboolean free_nodes)
1463{
1464 gboolean free_path = FALSE(0);
1465 FileBrowserNode *parent;
1466
1467 if (path == NULL((void*)0)) {
1468 path =
1469 pluma_file_browser_store_get_path_real (model, node);
1470 free_path = TRUE(!(0));
1471 }
1472
1473 model_remove_node_children (model, node, path, free_nodes);
1474
1475 /* Only delete if the node is visible in the tree (but only when it's
1476 not the virtual root) */
1477 if (model_node_visibility (model, node) && node != model->priv->virtual_root)
1478 {
1479 node->inserted = FALSE(0);
1480 row_deleted (model, path);
1481 }
1482
1483 if (free_path)
1484 gtk_tree_path_free (path);
1485
1486 parent = node->parent;
1487
1488 if (free_nodes) {
1489 /* Remove the node from the parents children list */
1490 if (parent)
1491 FILE_BROWSER_NODE_DIR (node->parent)((FileBrowserNodeDir *)(node->parent))->children =
1492 g_slist_remove (FILE_BROWSER_NODE_DIR((FileBrowserNodeDir *)(node->parent))
1493 (node->parent)((FileBrowserNodeDir *)(node->parent))->children,
1494 node);
1495 }
1496
1497 /* If this is the virtual root, than set the parent as the virtual root */
1498 if (node == model->priv->virtual_root)
1499 set_virtual_root_from_node (model, parent);
1500 else if (parent && model_node_visibility (model, parent) && !(free_nodes && NODE_IS_DUMMY(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
))
1501 model_check_dummy (model, parent);
1502
1503 /* Now free the node if necessary */
1504 if (free_nodes)
1505 file_browser_node_free (model, node);
1506}
1507
1508/**
1509 * model_clear:
1510 * @model: the #PlumaFileBrowserStore
1511 * @free_nodes: whether to also remove the nodes from memory
1512 *
1513 * Removes all nodes from the model. This function is used
1514 * to remove all the nodes from the _model_. Don't use it to just free the
1515 * nodes in the model.
1516 **/
1517static void
1518model_clear (PlumaFileBrowserStore * model, gboolean free_nodes)
1519{
1520 GtkTreePath *path;
1521 FileBrowserNodeDir *dir;
1522 FileBrowserNode *dummy;
1523
1524 path = gtk_tree_path_new ();
1525 model_remove_node_children (model, model->priv->virtual_root, path,
1526 free_nodes);
1527 gtk_tree_path_free (path);
1528
1529 /* Remove the dummy if there is one */
1530 if (model->priv->virtual_root) {
1531 dir = FILE_BROWSER_NODE_DIR (model->priv->virtual_root)((FileBrowserNodeDir *)(model->priv->virtual_root));
1532
1533 if (dir->children != NULL((void*)0)) {
1534 dummy = (FileBrowserNode *) (dir->children->data);
1535
1536 if (NODE_IS_DUMMY (dummy)(((dummy)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
1537 && model_node_visibility (model, dummy)) {
1538 path = gtk_tree_path_new_first ();
1539
1540 dummy->inserted = FALSE(0);
1541 row_deleted (model, path);
1542 gtk_tree_path_free (path);
1543 }
1544 }
1545 }
1546}
1547
1548static void
1549file_browser_node_unload (PlumaFileBrowserStore * model,
1550 FileBrowserNode * node, gboolean remove_children)
1551{
1552 FileBrowserNodeDir *dir;
1553
1554 if (node == NULL((void*)0))
1555 return;
1556
1557 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
|| !NODE_LOADED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
)
1558 return;
1559
1560 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
1561
1562 if (remove_children)
1563 model_remove_node_children (model, node, NULL((void*)0), TRUE(!(0)));
1564
1565 if (dir->cancellable) {
1566 g_cancellable_cancel (dir->cancellable);
1567 g_object_unref (dir->cancellable);
1568
1569 model_end_loading (model, node);
1570 dir->cancellable = NULL((void*)0);
1571 }
1572
1573 if (dir->monitor) {
1574 g_file_monitor_cancel (dir->monitor);
1575 g_object_unref (dir->monitor);
1576
1577 dir->monitor = NULL((void*)0);
1578 }
1579
1580 node->flags &= ~PLUMA_FILE_BROWSER_STORE_FLAG_LOADED;
1581}
1582
1583static void
1584model_recomposite_icon_real (PlumaFileBrowserStore * tree_model,
1585 FileBrowserNode * node,
1586 GFileInfo * info)
1587{
1588 GdkPixbuf *icon;
1589
1590 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_125
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_125 = 1; else _g_boolean_var_125 =
0; _g_boolean_var_125; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return; } } while (0)
;
1591 g_return_if_fail (node != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_126
; if (node != ((void*)0)) _g_boolean_var_126 = 1; else _g_boolean_var_126
= 0; _g_boolean_var_126; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "node != NULL"); return
; } } while (0)
;
1592
1593 if (node->file == NULL((void*)0))
1594 return;
1595
1596 if (info) {
1597 GIcon *gicon = g_file_info_get_icon (info);
1598 if (gicon != NULL((void*)0))
1599 icon = pluma_file_browser_utils_pixbuf_from_icon (gicon, GTK_ICON_SIZE_MENU);
1600 else
1601 icon = NULL((void*)0);
1602 } else {
1603 icon = pluma_file_browser_utils_pixbuf_from_file (node->file, GTK_ICON_SIZE_MENU);
1604 }
1605
1606 if (node->icon)
1607 g_object_unref (node->icon);
1608
1609 if (node->emblem) {
1610 gint icon_size;
1611
1612 gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL((void*)0), &icon_size);
1613
1614 if (icon == NULL((void*)0)) {
1615 node->icon =
1616 gdk_pixbuf_new (gdk_pixbuf_get_colorspace (node->emblem),
1617 gdk_pixbuf_get_has_alpha (node->emblem),
1618 gdk_pixbuf_get_bits_per_sample (node->emblem),
1619 icon_size,
1620 icon_size);
1621 } else {
1622 node->icon = gdk_pixbuf_copy (icon);
1623 g_object_unref (icon);
1624 }
1625
1626 gdk_pixbuf_composite (node->emblem, node->icon,
1627 icon_size - 10, icon_size - 10, 10,
1628 10, icon_size - 10, icon_size - 10,
1629 1, 1, GDK_INTERP_NEAREST, 255);
1630 } else {
1631 node->icon = icon;
1632 }
1633}
1634
1635static void
1636model_recomposite_icon (PlumaFileBrowserStore * tree_model,
1637 GtkTreeIter * iter)
1638{
1639 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_127
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_127 = 1; else _g_boolean_var_127 =
0; _g_boolean_var_127; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return; } } while (0)
;
1640 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_128
; if (iter != ((void*)0)) _g_boolean_var_128 = 1; else _g_boolean_var_128
= 0; _g_boolean_var_128; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
1641 g_return_if_fail (iter->user_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_129
; if (iter->user_data != ((void*)0)) _g_boolean_var_129 = 1
; else _g_boolean_var_129 = 0; _g_boolean_var_129; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return; } } while
(0)
;
1642
1643 model_recomposite_icon_real (tree_model,
1644 (FileBrowserNode *) (iter->user_data),
1645 NULL((void*)0));
1646}
1647
1648static FileBrowserNode *
1649model_create_dummy_node (PlumaFileBrowserStore * model,
1650 FileBrowserNode * parent)
1651{
1652 FileBrowserNode *dummy;
1653
1654 dummy = file_browser_node_new (NULL((void*)0), parent);
1655 dummy->name = g_strdup (_("(Empty)"))g_strdup_inline (((char *) g_dgettext ("pluma", "(Empty)")));
1656
1657 dummy->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY;
1658 dummy->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1659
1660 return dummy;
1661}
1662
1663static FileBrowserNode *
1664model_add_dummy_node (PlumaFileBrowserStore * model,
1665 FileBrowserNode * parent)
1666{
1667 FileBrowserNode *dummy;
1668
1669 dummy = model_create_dummy_node (model, parent);
1670
1671 if (model_node_visibility (model, parent))
1672 dummy->flags &= ~PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1673
1674 model_add_node (model, dummy, parent);
1675
1676 return dummy;
1677}
1678
1679static void
1680model_check_dummy (PlumaFileBrowserStore * model, FileBrowserNode * node)
1681{
1682 // Hide the dummy child if needed
1683 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
1684 FileBrowserNode *dummy;
1685 GtkTreeIter iter;
1686 GtkTreePath *path;
1687 guint flags;
1688 FileBrowserNodeDir *dir;
1689
1690 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
1691
1692 if (dir->children == NULL((void*)0)) {
1693 model_add_dummy_node (model, node);
1694 return;
1695 }
1696
1697 dummy = (FileBrowserNode *) (dir->children->data);
1698
1699 if (!NODE_IS_DUMMY (dummy)(((dummy)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
) {
1700 dummy = model_create_dummy_node (model, node);
1701 dir->children = g_slist_prepend (dir->children, dummy);
1702 }
1703
1704 if (!model_node_visibility (model, node)) {
1705 dummy->flags |=
1706 PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1707 return;
1708 }
1709
1710 /* Temporarily set the node to invisible to check
1711 * for real children */
1712 flags = dummy->flags;
1713 dummy->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1714
1715 if (!filter_tree_model_iter_has_child_real (model, node)) {
1716 dummy->flags &=
1717 ~PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1718
1719 if (FILE_IS_HIDDEN (flags)(flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN)) {
1720 // Was hidden, needs to be inserted
1721 iter.user_data = dummy;
1722 path =
1723 pluma_file_browser_store_get_path_real
1724 (model, dummy);
1725
1726 row_inserted (model, &path, &iter);
1727 gtk_tree_path_free (path);
1728 }
1729 } else {
1730 if (!FILE_IS_HIDDEN (flags)(flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN)) {
1731 // Was shown, needs to be removed
1732
1733 // To get the path we need to set it to visible temporarily
1734 dummy->flags &=
1735 ~PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1736 path =
1737 pluma_file_browser_store_get_path_real
1738 (model, dummy);
1739 dummy->flags |=
1740 PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1741
1742 dummy->inserted = FALSE(0);
1743 row_deleted (model, path);
1744 gtk_tree_path_free (path);
1745 }
1746 }
1747 }
1748}
1749
1750static void
1751insert_node_sorted (PlumaFileBrowserStore * model,
1752 FileBrowserNode * child,
1753 FileBrowserNode * parent)
1754{
1755 FileBrowserNodeDir *dir;
1756
1757 dir = FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent));
1758
1759 if (model->priv->sort_func == NULL((void*)0)) {
1760 dir->children = g_slist_append (dir->children, child);
1761 } else {
1762 dir->children =
1763 g_slist_insert_sorted (dir->children, child,
1764 (GCompareFunc) (model->priv->
1765 sort_func));
1766 }
1767}
1768
1769static void
1770model_add_node (PlumaFileBrowserStore * model, FileBrowserNode * child,
1771 FileBrowserNode * parent)
1772{
1773 /* Add child to parents children */
1774 insert_node_sorted (model, child, parent);
1775
1776 if (model_node_visibility (model, parent) &&
1777 model_node_visibility (model, child)) {
1778 GtkTreeIter iter;
1779 GtkTreePath *path;
1780
1781 iter.user_data = child;
1782 path = pluma_file_browser_store_get_path_real (model, child);
1783
1784 /* Emit row inserted */
1785 row_inserted (model, &path, &iter);
1786 gtk_tree_path_free (path);
1787 }
1788
1789 model_check_dummy (model, parent);
1790 model_check_dummy (model, child);
1791}
1792
1793static void
1794model_add_nodes_batch (PlumaFileBrowserStore * model,
1795 GSList * children,
1796 FileBrowserNode * parent)
1797{
1798 GSList *sorted_children;
1799 GSList *child;
1800 GSList *prev;
1801 GSList *l;
1802 FileBrowserNodeDir *dir;
1803
1804 dir = FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent));
1805
1806 sorted_children = g_slist_sort (children, (GCompareFunc) model->priv->sort_func);
1807
1808 child = sorted_children;
1809 l = dir->children;
1810 prev = NULL((void*)0);
1811
1812 model_check_dummy (model, parent);
1813
1814 while (child) {
1815 FileBrowserNode *node = child->data;
1816 GtkTreeIter iter;
1817 GtkTreePath *path;
1818
1819 /* reached the end of the first list, just append the second */
1820 if (l == NULL((void*)0)) {
1821
1822 dir->children = g_slist_concat (dir->children, child);
1823
1824 for (l = child; l; l = l->next) {
1825 if (model_node_visibility (model, parent) &&
1826 model_node_visibility (model, l->data)) {
1827 iter.user_data = l->data;
1828 path = pluma_file_browser_store_get_path_real (model, l->data);
1829
1830 // Emit row inserted
1831 row_inserted (model, &path, &iter);
1832 gtk_tree_path_free (path);
1833 }
1834
1835 model_check_dummy (model, l->data);
1836 }
1837
1838 break;
1839 }
1840
1841 if (model->priv->sort_func (l->data, node) > 0) {
1842 GSList *next_child;
1843
1844 if (prev == NULL((void*)0)) {
1845 /* prepend to the list */
1846 dir->children = g_slist_prepend (dir->children, child);
1847 } else {
1848 prev->next = child;
1849 }
1850
1851 next_child = child->next;
1852 prev = child;
1853 child->next = l;
1854 child = next_child;
1855
1856 if (model_node_visibility (model, parent) &&
1857 model_node_visibility (model, node)) {
1858 iter.user_data = node;
1859 path = pluma_file_browser_store_get_path_real (model, node);
1860
1861 // Emit row inserted
1862 row_inserted (model, &path, &iter);
1863 gtk_tree_path_free (path);
1864 }
1865
1866 model_check_dummy (model, node);
1867
1868 /* try again at the same l position with the
1869 * next child */
1870 } else {
1871
1872 /* Move to the next item in the list */
1873 prev = l;
1874 l = l->next;
1875 }
1876 }
1877}
1878
1879static gchar const *
1880backup_content_type (GFileInfo * info)
1881{
1882 gchar const * content;
1883
1884 if (!g_file_info_get_is_backup (info))
1885 return NULL((void*)0);
1886
1887 content = g_file_info_get_content_type (info);
1888
1889 if (!content || g_content_type_equals (content, "application/x-trash"))
1890 return "text/plain";
1891
1892 return content;
1893}
1894
1895static void
1896file_browser_node_set_from_info (PlumaFileBrowserStore * model,
1897 FileBrowserNode * node,
1898 GFileInfo * info,
1899 gboolean isadded)
1900{
1901 gchar const * content;
1902 gboolean free_info = FALSE(0);
1903 GtkTreePath * path;
1904 gchar * uri;
1905 GError * error = NULL((void*)0);
1906
1907 if (info == NULL((void*)0)) {
1908 info = g_file_query_info (node->file,
1909 STANDARD_ATTRIBUTE_TYPES"standard::type" "," "standard::is-hidden" "," "standard::is-backup"
"," "standard::name" "," "standard::content-type" "," "standard::icon"
,
1910 G_FILE_QUERY_INFO_NONE,
1911 NULL((void*)0),
1912 &error);
1913
1914 if (!info) {
1915 if (!(error->domain == G_IO_ERRORg_io_error_quark() && error->code == G_IO_ERROR_NOT_FOUND)) {
1916 uri = g_file_get_uri (node->file);
1917 g_warning ("Could not get info for %s: %s", uri, error->message);
1918 g_free (uri);
1919 }
1920 g_error_free (error);
1921
1922 return;
1923 }
1924
1925 free_info = TRUE(!(0));
1926 }
1927
1928 if (g_file_info_get_is_hidden (info) || g_file_info_get_is_backup (info))
1929 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1930
1931 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
1932 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY;
1933 else {
1934 if (!(content = backup_content_type (info)))
1935 content = g_file_info_get_content_type (info);
1936
1937 if (!content ||
1938 g_content_type_is_unknown (content) ||
1939 g_content_type_is_a (content, "text/plain"))
1940 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_TEXT;
1941 }
1942
1943 model_recomposite_icon_real (model, node, info);
1944
1945 if (free_info)
1946 g_object_unref (info);
1947
1948 if (isadded) {
1949 path = pluma_file_browser_store_get_path_real (model, node);
1950 model_refilter_node (model, node, &path);
1951 gtk_tree_path_free (path);
1952
1953 model_check_dummy (model, node->parent);
1954 } else {
1955 model_node_update_visibility (model, node);
1956 }
1957}
1958
1959static FileBrowserNode *
1960node_list_contains_file (GSList *children, GFile * file)
1961{
1962 GSList *item;
1963
1964 for (item = children; item; item = item->next) {
1965 FileBrowserNode *node;
1966
1967 node = (FileBrowserNode *) (item->data);
1968
1969 if (node->file != NULL((void*)0)
1970 && g_file_equal (node->file, file))
1971 return node;
1972 }
1973
1974 return NULL((void*)0);
1975}
1976
1977static FileBrowserNode *
1978model_add_node_from_file (PlumaFileBrowserStore * model,
1979 FileBrowserNode * parent,
1980 GFile * file,
1981 GFileInfo * info)
1982{
1983 FileBrowserNode *node;
1984 gboolean free_info = FALSE(0);
1985 GError * error = NULL((void*)0);
1986
1987 if ((node = node_list_contains_file (FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent))->children, file)) == NULL((void*)0)) {
1988 if (info == NULL((void*)0)) {
1989 info = g_file_query_info (file,
1990 STANDARD_ATTRIBUTE_TYPES"standard::type" "," "standard::is-hidden" "," "standard::is-backup"
"," "standard::name" "," "standard::content-type" "," "standard::icon"
,
1991 G_FILE_QUERY_INFO_NONE,
1992 NULL((void*)0),
1993 &error);
1994 free_info = TRUE(!(0));
1995 }
1996
1997 if (!info) {
1998 g_warning ("Error querying file info: %s", error->message);
1999 g_error_free (error);
2000
2001 /* FIXME: What to do now then... */
2002 node = file_browser_node_new (file, parent);
2003 } else if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
2004 node = file_browser_node_dir_new (model, file, parent);
2005 } else {
2006 node = file_browser_node_new (file, parent);
2007 }
2008
2009 file_browser_node_set_from_info (model, node, info, FALSE(0));
2010 model_add_node (model, node, parent);
2011
2012 if (info && free_info)
2013 g_object_unref (info);
2014 }
2015
2016 return node;
2017}
2018
2019/* We pass in a copy of the list of parent->children so that we do
2020 * not have to check if a file already exists among the ones we just
2021 * added */
2022static void
2023model_add_nodes_from_files (PlumaFileBrowserStore * model,
2024 FileBrowserNode * parent,
2025 GSList * original_children,
2026 GList * files)
2027{
2028 GList *item;
2029 GSList *nodes = NULL((void*)0);
2030
2031 for (item = files; item; item = item->next) {
2032 GFileInfo *info = G_FILE_INFO (item->data)((((GFileInfo*) (void *) ((item->data)))));
2033 GFileType type;
2034 gchar const * name;
2035 GFile * file;
2036 FileBrowserNode *node;
2037
2038 type = g_file_info_get_file_type (info);
2039
2040 /* Skip all non regular, non directory files */
2041 if (type != G_FILE_TYPE_REGULAR &&
2042 type != G_FILE_TYPE_DIRECTORY &&
2043 type != G_FILE_TYPE_SYMBOLIC_LINK) {
2044 g_object_unref (info);
2045 continue;
2046 }
2047
2048 name = g_file_info_get_name (info);
2049
2050 /* Skip '.' and '..' directories */
2051 if (type == G_FILE_TYPE_DIRECTORY &&
2052 (strcmp (name, ".") == 0 ||
2053 strcmp (name, "..") == 0)) {
2054 continue;
2055 }
2056
2057 file = g_file_get_child (parent->file, name);
2058
2059 if ((node = node_list_contains_file (original_children, file)) == NULL((void*)0)) {
2060
2061 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
2062 node = file_browser_node_dir_new (model, file, parent);
2063 } else {
2064 node = file_browser_node_new (file, parent);
2065 }
2066
2067 file_browser_node_set_from_info (model, node, info, FALSE(0));
2068
2069 nodes = g_slist_prepend (nodes, node);
2070 }
2071
2072 g_object_unref (file);
2073 g_object_unref (info);
2074 }
2075
2076 if (nodes)
2077 model_add_nodes_batch (model, nodes, parent);
2078}
2079
2080static FileBrowserNode *
2081model_add_node_from_dir (PlumaFileBrowserStore * model,
2082 FileBrowserNode * parent,
2083 GFile * file)
2084{
2085 FileBrowserNode *node;
2086
2087 /* Check if it already exists */
2088 if ((node = node_list_contains_file (FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent))->children, file)) == NULL((void*)0)) {
2089 node = file_browser_node_dir_new (model, file, parent);
2090 file_browser_node_set_from_info (model, node, NULL((void*)0), FALSE(0));
2091
2092 if (node->name == NULL((void*)0)) {
2093 file_browser_node_set_name (node);
2094 }
2095
2096 if (node->icon == NULL((void*)0)) {
2097 node->icon = pluma_file_browser_utils_pixbuf_from_theme ("folder", GTK_ICON_SIZE_MENU);
2098 }
2099
2100 model_add_node (model, node, parent);
2101 }
2102
2103 return node;
2104}
2105
2106static void
2107on_directory_monitor_event (GFileMonitor * monitor,
2108 GFile * file,
2109 GFile * other_file,
2110 GFileMonitorEvent event_type,
2111 FileBrowserNode * parent)
2112{
2113 FileBrowserNode *node;
2114 FileBrowserNodeDir *dir = FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent));
2115
2116 switch (event_type) {
2117 case G_FILE_MONITOR_EVENT_DELETED:
2118 node = node_list_contains_file (dir->children, file);
2119
2120 if (node != NULL((void*)0)) {
2121 model_remove_node (dir->model, node, NULL((void*)0), TRUE(!(0)));
2122 }
2123 break;
2124 case G_FILE_MONITOR_EVENT_CREATED:
2125 if (g_file_query_exists (file, NULL((void*)0))) {
2126 model_add_node_from_file (dir->model, parent, file, NULL((void*)0));
2127 }
2128
2129 break;
2130 default:
2131 break;
2132 }
2133}
2134
2135static void
2136async_node_free (AsyncNode *async)
2137{
2138 g_object_unref (async->cancellable);
2139 g_slist_free (async->original_children);
2140 g_free (async);
2141}
2142
2143static void
2144model_iterate_next_files_cb (GFileEnumerator * enumerator,
2145 GAsyncResult * result,
2146 AsyncNode * async)
2147{
2148 GList * files;
2149 GError * error = NULL((void*)0);
2150 FileBrowserNodeDir * dir = async->dir;
2151 FileBrowserNode * parent = (FileBrowserNode *)dir;
2152
2153 files = g_file_enumerator_next_files_finish (enumerator, result, &error);
2154
2155 if (files == NULL((void*)0)) {
2156 g_file_enumerator_close (enumerator, NULL((void*)0), NULL((void*)0));
2157 async_node_free (async);
2158
2159 if (!error)
2160 {
2161 /* We're done loading */
2162 g_object_unref (dir->cancellable);
2163 dir->cancellable = NULL((void*)0);
2164
2165/*
2166 * FIXME: This is temporarly, it is a bug in gio:
2167 * http://bugzilla.gnome.org/show_bug.cgi?id=565924
2168 */
2169 if (g_file_is_native (parent->file) && dir->monitor == NULL((void*)0)) {
2170 dir->monitor = g_file_monitor_directory (parent->file,
2171 G_FILE_MONITOR_NONE,
2172 NULL((void*)0),
2173 NULL((void*)0));
2174 if (dir->monitor != NULL((void*)0))
2175 {
2176 g_signal_connect (dir->monitor,g_signal_connect_data ((dir->monitor), ("changed"), (((GCallback
) (on_directory_monitor_event))), (parent), ((void*)0), (GConnectFlags
) 0)
2177 "changed",g_signal_connect_data ((dir->monitor), ("changed"), (((GCallback
) (on_directory_monitor_event))), (parent), ((void*)0), (GConnectFlags
) 0)
2178 G_CALLBACK (on_directory_monitor_event),g_signal_connect_data ((dir->monitor), ("changed"), (((GCallback
) (on_directory_monitor_event))), (parent), ((void*)0), (GConnectFlags
) 0)
2179 parent)g_signal_connect_data ((dir->monitor), ("changed"), (((GCallback
) (on_directory_monitor_event))), (parent), ((void*)0), (GConnectFlags
) 0)
;
2180 }
2181 }
2182
2183 model_check_dummy (dir->model, parent);
2184 model_end_loading (dir->model, parent);
2185 } else {
2186 /* Simply return if we were cancelled */
2187 if (error->domain == G_IO_ERRORg_io_error_quark() && error->code == G_IO_ERROR_CANCELLED)
2188 return;
2189
2190 /* Otherwise handle the error appropriately */
2191 g_signal_emit (dir->model,
2192 model_signals[ERROR],
2193 0,
2194 PLUMA_FILE_BROWSER_ERROR_LOAD_DIRECTORY,
2195 error->message);
2196
2197 file_browser_node_unload (dir->model, (FileBrowserNode *)parent, TRUE(!(0)));
2198 g_error_free (error);
2199 }
2200 } else if (g_cancellable_is_cancelled (async->cancellable)) {
2201 /* Check cancel state manually */
2202 g_file_enumerator_close (enumerator, NULL((void*)0), NULL((void*)0));
2203 async_node_free (async);
2204 } else {
2205 model_add_nodes_from_files (dir->model, parent, async->original_children, files);
2206
2207 g_list_free (files);
2208 next_files_async (enumerator, async);
2209 }
2210}
2211
2212static void
2213next_files_async (GFileEnumerator * enumerator,
2214 AsyncNode * async)
2215{
2216 g_file_enumerator_next_files_async (enumerator,
2217 DIRECTORY_LOAD_ITEMS_PER_CALLBACK100,
2218 G_PRIORITY_DEFAULT0,
2219 async->cancellable,
2220 (GAsyncReadyCallback)model_iterate_next_files_cb,
2221 async);
2222}
2223
2224static void
2225model_iterate_children_cb (GFile * file,
2226 GAsyncResult * result,
2227 AsyncNode * async)
2228{
2229 GError * error = NULL((void*)0);
2230 GFileEnumerator * enumerator;
2231
2232 if (g_cancellable_is_cancelled (async->cancellable))
2233 {
2234 async_node_free (async);
2235 return;
2236 }
2237
2238 enumerator = g_file_enumerate_children_finish (file, result, &error);
2239
2240 if (enumerator == NULL((void*)0)) {
2241 /* Simply return if we were cancelled or if the dir is not there */
2242 FileBrowserNodeDir *dir = async->dir;
2243
2244 /* Otherwise handle the error appropriately */
2245 g_signal_emit (dir->model,
2246 model_signals[ERROR],
2247 0,
2248 PLUMA_FILE_BROWSER_ERROR_LOAD_DIRECTORY,
2249 error->message);
2250
2251 file_browser_node_unload (dir->model, (FileBrowserNode *)dir, TRUE(!(0)));
2252 g_error_free (error);
2253 async_node_free (async);
2254 } else {
2255 next_files_async (enumerator, async);
2256 }
2257}
2258
2259static void
2260model_load_directory (PlumaFileBrowserStore * model,
2261 FileBrowserNode * node)
2262{
2263 FileBrowserNodeDir *dir;
2264 AsyncNode *async;
2265
2266 g_return_if_fail (NODE_IS_DIR (node))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_130
; if ((((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))) _g_boolean_var_130 = 1; else _g_boolean_var_130 = 0; _g_boolean_var_130
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "NODE_IS_DIR (node)"); return; }
} while (0)
;
2267
2268 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
2269
2270 /* Cancel a previous load */
2271 if (dir->cancellable != NULL((void*)0)) {
2272 file_browser_node_unload (dir->model, node, TRUE(!(0)));
2273 }
2274
2275 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_LOADED;
2276 model_begin_loading (model, node);
2277
2278 dir->cancellable = g_cancellable_new ();
2279
2280 async = g_new (AsyncNode, 1)(AsyncNode *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (AsyncNode); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
2281 async->dir = dir;
2282 async->cancellable = g_object_ref (dir->cancellable)((__typeof__ (dir->cancellable)) (g_object_ref) (dir->cancellable
))
;
2283 async->original_children = g_slist_copy (dir->children);
2284
2285 /* Start loading async */
2286 g_file_enumerate_children_async (node->file,
2287 STANDARD_ATTRIBUTE_TYPES"standard::type" "," "standard::is-hidden" "," "standard::is-backup"
"," "standard::name" "," "standard::content-type" "," "standard::icon"
,
2288 G_FILE_QUERY_INFO_NONE,
2289 G_PRIORITY_DEFAULT0,
2290 async->cancellable,
2291 (GAsyncReadyCallback)model_iterate_children_cb,
2292 async);
2293}
2294
2295static GList *
2296get_parent_files (PlumaFileBrowserStore * model, GFile * file)
2297{
2298 GList * result = NULL((void*)0);
2299
2300 result = g_list_prepend (result, g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)));
2301
2302 while ((file = g_file_get_parent (file))) {
2303 if (g_file_equal (file, model->priv->root->file)) {
2304 g_object_unref (file);
2305 break;
2306 }
2307
2308 result = g_list_prepend (result, file);
2309 }
2310
2311 return result;
2312}
2313
2314static void
2315model_fill (PlumaFileBrowserStore * model, FileBrowserNode * node,
2316 GtkTreePath ** path)
2317{
2318 gboolean free_path = FALSE(0);
2319 GtkTreeIter iter = {0,};
2320 GSList *item;
2321 FileBrowserNode *child;
2322
2323 if (node == NULL((void*)0)) {
2324 node = model->priv->virtual_root;
2325 *path = gtk_tree_path_new ();
2326 free_path = TRUE(!(0));
2327 }
2328
2329 if (*path == NULL((void*)0)) {
2330 *path =
2331 pluma_file_browser_store_get_path_real (model, node);
2332 free_path = TRUE(!(0));
2333 }
2334
2335 if (!model_node_visibility (model, node)) {
2336 if (free_path)
2337 gtk_tree_path_free (*path);
2338
2339 return;
2340 }
2341
2342 if (node != model->priv->virtual_root) {
2343 /* Insert node */
2344 iter.user_data = node;
2345
2346 row_inserted(model, path, &iter);
2347 }
2348
2349 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
2350 /* Go to the first child */
2351 gtk_tree_path_down (*path);
2352
2353 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item;
2354 item = item->next) {
2355 child = (FileBrowserNode *) (item->data);
2356
2357 if (model_node_visibility (model, child)) {
2358 model_fill (model, child, path);
2359
2360 /* Increase path for next child */
2361 gtk_tree_path_next (*path);
2362 }
2363 }
2364
2365 /* Move back up to node path */
2366 gtk_tree_path_up (*path);
2367 }
2368
2369 model_check_dummy (model, node);
2370
2371 if (free_path)
2372 gtk_tree_path_free (*path);
2373}
2374
2375static void
2376set_virtual_root_from_node (PlumaFileBrowserStore * model,
2377 FileBrowserNode * node)
2378{
2379 FileBrowserNode *next;
2380 FileBrowserNode *prev;
2381 FileBrowserNode *check;
2382 FileBrowserNodeDir *dir;
2383 GSList *item;
2384 GSList *copy;
2385 GtkTreePath *empty = NULL((void*)0);
2386
2387 g_assert (node != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_131
; if (node != ((void*)0)) _g_boolean_var_131 = 1; else _g_boolean_var_131
= 0; _g_boolean_var_131; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "pluma-file-browser-store.c", 2387, ((const char
*) (__func__)), "node != NULL"); } while (0)
;
2388
2389 prev = node;
2390 next = prev->parent;
2391
2392 /* Free all the nodes below that we don't need in cache */
2393 while (prev != model->priv->root) {
2394 dir = FILE_BROWSER_NODE_DIR (next)((FileBrowserNodeDir *)(next));
2395 copy = g_slist_copy (dir->children);
2396
2397 for (item = copy; item; item = item->next) {
2398 check = (FileBrowserNode *) (item->data);
2399
2400 if (prev == node) {
2401 /* Only free the children, keeping this depth in cache */
2402 if (check != node) {
2403 file_browser_node_free_children
2404 (model, check);
2405 file_browser_node_unload (model,
2406 check,
2407 FALSE(0));
2408 }
2409 } else if (check != prev) {
2410 /* Only free when the node is not in the chain */
2411 dir->children =
2412 g_slist_remove (dir->children, check);
2413 file_browser_node_free (model, check);
2414 }
2415 }
2416
2417 if (prev != node)
2418 file_browser_node_unload (model, next, FALSE(0));
2419
2420 g_slist_free (copy);
2421 prev = next;
2422 next = prev->parent;
2423 }
2424
2425 /* Free all the nodes up that we don't need in cache */
2426 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item;
2427 item = item->next) {
2428 check = (FileBrowserNode *) (item->data);
2429
2430 if (NODE_IS_DIR (check)(((check)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
2431 for (copy =
2432 FILE_BROWSER_NODE_DIR (check)((FileBrowserNodeDir *)(check))->children; copy;
2433 copy = copy->next) {
2434 file_browser_node_free_children (model,
2435 (FileBrowserNode
2436 *)
2437 (copy->
2438 data));
2439 file_browser_node_unload (model,
2440 (FileBrowserNode
2441 *) (copy->data),
2442 FALSE(0));
2443 }
2444 } else if (NODE_IS_DUMMY (check)(((check)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
) {
2445 check->flags |=
2446 PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
2447 }
2448 }
2449
2450 /* Now finally, set the virtual root, and load it up! */
2451 model->priv->virtual_root = node;
2452
2453 /* Notify that the virtual-root has changed before loading up new nodes so that the
2454 "root_changed" signal can be emitted before any "inserted" signals */
2455 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "virtual-root");
2456
2457 model_fill (model, NULL((void*)0), &empty);
2458
2459 if (!NODE_LOADED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
)
2460 model_load_directory (model, node);
2461}
2462
2463static void
2464set_virtual_root_from_file (PlumaFileBrowserStore * model,
2465 GFile * file)
2466{
2467 GList * files;
2468 GList * item;
2469 FileBrowserNode * parent;
2470 GFile * check;
2471
2472 /* Always clear the model before altering the nodes */
2473 model_clear (model, FALSE(0));
2474
2475 /* Create the node path, get all the uri's */
2476 files = get_parent_files (model, file);
2477 parent = model->priv->root;
2478
2479 for (item = files; item; item = item->next) {
2480 check = G_FILE (item->data)((((GFile*) (void *) ((item->data)))));
2481
2482 parent = model_add_node_from_dir (model, parent, check);
2483 g_object_unref (check);
2484 }
2485
2486 g_list_free (files);
2487 set_virtual_root_from_node (model, parent);
2488}
2489
2490static FileBrowserNode *
2491model_find_node_children (PlumaFileBrowserStore * model,
2492 FileBrowserNode * parent,
2493 GFile * file)
2494{
2495 FileBrowserNodeDir *dir;
2496 FileBrowserNode *child;
2497 FileBrowserNode *result;
2498 GSList *children;
2499
2500 if (!NODE_IS_DIR (parent)(((parent)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
2501 return NULL((void*)0);
2502
2503 dir = FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent));
2504
2505 for (children = dir->children; children; children = children->next) {
2506 child = (FileBrowserNode *)(children->data);
2507
2508 result = model_find_node (model, child, file);
2509
2510 if (result)
2511 return result;
2512 }
2513
2514 return NULL((void*)0);
2515}
2516
2517static FileBrowserNode *
2518model_find_node (PlumaFileBrowserStore * model,
2519 FileBrowserNode * node,
2520 GFile * file)
2521{
2522 if (node == NULL((void*)0))
2523 node = model->priv->root;
2524
2525 if (node->file && g_file_equal (node->file, file))
2526 return node;
2527
2528 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
&& g_file_has_prefix (file, node->file))
2529 return model_find_node_children (model, node, file);
2530
2531 return NULL((void*)0);
2532}
2533
2534static GQuark
2535pluma_file_browser_store_error_quark (void)
2536{
2537 static GQuark quark = 0;
2538
2539 if (G_UNLIKELY (quark == 0)(__builtin_expect (__extension__ ({ int _g_boolean_var_132; if
(quark == 0) _g_boolean_var_132 = 1; else _g_boolean_var_132
= 0; _g_boolean_var_132; }), 0))
) {
2540 quark = g_quark_from_string ("pluma_file_browser_store_error");
2541 }
2542
2543 return quark;
2544}
2545
2546static GFile *
2547unique_new_name (GFile * directory, gchar const * name)
2548{
2549 GFile * newuri = NULL((void*)0);
2550 guint num = 0;
2551 gchar * newname;
2552
2553 while (newuri == NULL((void*)0) || g_file_query_exists (newuri, NULL((void*)0))) {
2554 if (newuri != NULL((void*)0))
2555 g_object_unref (newuri);
2556
2557 if (num == 0)
2558 newname = g_strdup (name)g_strdup_inline (name);
2559 else
2560 newname = g_strdup_printf ("%s(%d)", name, num);
2561
2562 newuri = g_file_get_child (directory, newname);
2563 g_free (newname);
2564
2565 ++num;
2566 }
2567
2568 return newuri;
2569}
2570
2571static PlumaFileBrowserStoreResult
2572model_root_mounted (PlumaFileBrowserStore * model, gchar const * virtual_root)
2573{
2574 model_check_dummy (model, model->priv->root);
2575 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "root");
2576
2577 if (virtual_root != NULL((void*)0))
2578 return
2579 pluma_file_browser_store_set_virtual_root_from_string
2580 (model, virtual_root);
2581 else
2582 set_virtual_root_from_node (model,
2583 model->priv->root);
2584
2585 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2586}
2587
2588static void
2589handle_root_error (PlumaFileBrowserStore * model, GError *error)
2590{
2591 FileBrowserNode * root;
2592
2593 g_signal_emit (model,
2594 model_signals[ERROR],
2595 0,
2596 PLUMA_FILE_BROWSER_ERROR_SET_ROOT,
2597 error->message);
2598
2599 /* Set the virtual root to the root */
2600 root = model->priv->root;
2601 model->priv->virtual_root = root;
2602
2603 /* Set the root to be loaded */
2604 root->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_LOADED;
2605
2606 /* Check the dummy */
2607 model_check_dummy (model, root);
2608
2609 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "root");
2610 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "virtual-root");
2611}
2612
2613static void
2614mount_cb (GFile * file,
2615 GAsyncResult * res,
2616 MountInfo * mount_info)
2617{
2618 gboolean mounted;
2619 GError * error = NULL((void*)0);
2620 PlumaFileBrowserStore * model = mount_info->model;
2621
2622 mounted = g_file_mount_enclosing_volume_finish (file, res, &error);
2623
2624 if (mount_info->model)
2625 {
2626 model->priv->mount_info = NULL((void*)0);
2627 model_end_loading (model, model->priv->root);
2628 }
2629
2630 if (!mount_info->model || g_cancellable_is_cancelled (mount_info->cancellable))
2631 {
2632 // Reset because it might be reused?
2633 g_cancellable_reset (mount_info->cancellable);
2634 }
2635 else if (mounted)
2636 {
2637 model_root_mounted (model, mount_info->virtual_root);
2638 }
2639 else if (error->code != G_IO_ERROR_CANCELLED)
2640 {
2641 handle_root_error (model, error);
2642 }
2643
2644 if (error)
2645 g_error_free (error);
2646
2647 g_object_unref (mount_info->operation);
2648 g_object_unref (mount_info->cancellable);
2649 g_free (mount_info->virtual_root);
2650
2651 g_free (mount_info);
2652}
2653
2654static PlumaFileBrowserStoreResult
2655model_mount_root (PlumaFileBrowserStore * model, gchar const * virtual_root)
2656{
2657 GFileInfo * info;
2658 GError * error = NULL((void*)0);
2659 MountInfo * mount_info;
2660
2661 info = g_file_query_info (model->priv->root->file,
2662 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type",
2663 G_FILE_QUERY_INFO_NONE,
2664 NULL((void*)0),
2665 &error);
2666
2667 if (!info) {
2668 if (error->code == G_IO_ERROR_NOT_MOUNTED) {
2669 /* Try to mount it */
2670 FILE_BROWSER_NODE_DIR (model->priv->root)((FileBrowserNodeDir *)(model->priv->root))->cancellable = g_cancellable_new ();
2671
2672 mount_info = g_new(MountInfo, 1)(MountInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (MountInfo); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
2673 mount_info->model = model;
2674 mount_info->virtual_root = g_strdup (virtual_root)g_strdup_inline (virtual_root);
2675
2676 /* FIXME: we should be setting the correct window */
2677 mount_info->operation = gtk_mount_operation_new (NULL((void*)0));
2678 mount_info->cancellable = g_object_ref (FILE_BROWSER_NODE_DIR (model->priv->root)->cancellable)((__typeof__ (((FileBrowserNodeDir *)(model->priv->root
))->cancellable)) (g_object_ref) (((FileBrowserNodeDir *)(
model->priv->root))->cancellable))
;
2679
2680 model_begin_loading (model, model->priv->root);
2681 g_file_mount_enclosing_volume (model->priv->root->file,
2682 G_MOUNT_MOUNT_NONE,
2683 mount_info->operation,
2684 mount_info->cancellable,
2685 (GAsyncReadyCallback)mount_cb,
2686 mount_info);
2687
2688 model->priv->mount_info = mount_info;
2689 return PLUMA_FILE_BROWSER_STORE_RESULT_MOUNTING;
2690 }
2691 else
2692 {
2693 handle_root_error (model, error);
2694 }
2695
2696 g_error_free (error);
2697 } else {
2698 g_object_unref (info);
2699
2700 return model_root_mounted (model, virtual_root);
2701 }
2702
2703 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2704}
2705
2706/* Public */
2707PlumaFileBrowserStore *
2708pluma_file_browser_store_new (gchar const *root)
2709{
2710 PlumaFileBrowserStore *obj =
2711 PLUMA_FILE_BROWSER_STORE (g_object_new((((PlumaFileBrowserStore*) (void *) ((g_object_new ((pluma_file_browser_store_get_type
()), ((void*)0)))))))
2712 (PLUMA_TYPE_FILE_BROWSER_STORE,((((PlumaFileBrowserStore*) (void *) ((g_object_new ((pluma_file_browser_store_get_type
()), ((void*)0)))))))
2713 NULL))((((PlumaFileBrowserStore*) (void *) ((g_object_new ((pluma_file_browser_store_get_type
()), ((void*)0)))))))
;
2714
2715 pluma_file_browser_store_set_root (obj, root);
2716 return obj;
2717}
2718
2719void
2720pluma_file_browser_store_set_value (PlumaFileBrowserStore * tree_model,
2721 GtkTreeIter * iter, gint column,
2722 GValue * value)
2723{
2724 gpointer data;
2725 FileBrowserNode *node;
2726 GtkTreePath *path;
2727
2728 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_133
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_133 = 1; else _g_boolean_var_133 =
0; _g_boolean_var_133; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return; } } while (0)
;
2729 g_return_if_fail (column ==do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_134
; if (column == PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM) _g_boolean_var_134
= 1; else _g_boolean_var_134 = 0; _g_boolean_var_134; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "column == PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM"
); return; } } while (0)
2730 PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_134
; if (column == PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM) _g_boolean_var_134
= 1; else _g_boolean_var_134 = 0; _g_boolean_var_134; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "column == PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM"
); return; } } while (0)
;
2731 g_return_if_fail (G_VALUE_HOLDS_OBJECT (value))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_135
; if ((((__extension__ ({ const GValue *__val = (const GValue
*) ((value)); GType __t = (((GType) ((20) << (2)))); gboolean
__r; if (!__val) __r = (0); else if (__val->g_type == __t
) __r = (!(0)); else __r = g_type_check_value_holds (__val, __t
); __r; }))))) _g_boolean_var_135 = 1; else _g_boolean_var_135
= 0; _g_boolean_var_135; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "G_VALUE_HOLDS_OBJECT (value)"
); return; } } while (0)
;
2732 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_136
; if (iter != ((void*)0)) _g_boolean_var_136 = 1; else _g_boolean_var_136
= 0; _g_boolean_var_136; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
2733 g_return_if_fail (iter->user_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_137
; if (iter->user_data != ((void*)0)) _g_boolean_var_137 = 1
; else _g_boolean_var_137 = 0; _g_boolean_var_137; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return; } } while
(0)
;
2734
2735 data = g_value_get_object (value);
2736
2737 if (data)
2738 g_return_if_fail (GDK_IS_PIXBUF (data))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_138
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((data)); GType __t = ((gdk_pixbuf_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_138
= 1; else _g_boolean_var_138 = 0; _g_boolean_var_138; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "GDK_IS_PIXBUF (data)"); return; } } while
(0)
;
2739
2740 node = (FileBrowserNode *) (iter->user_data);
2741
2742 if (node->emblem)
2743 g_object_unref (node->emblem);
2744
2745 if (data)
2746 node->emblem = g_object_ref (GDK_PIXBUF (data))((__typeof__ (((((GdkPixbuf*) (void *) ((data))))))) (g_object_ref
) (((((GdkPixbuf*) (void *) ((data)))))))
;
2747 else
2748 node->emblem = NULL((void*)0);
2749
2750 model_recomposite_icon (tree_model, iter);
2751
2752 if (model_node_visibility (tree_model, node)) {
2753 path = pluma_file_browser_store_get_path (GTK_TREE_MODEL (tree_model)((((GtkTreeModel*) (void *) ((tree_model))))),
2754 iter);
2755 row_changed (tree_model, &path, iter);
2756 gtk_tree_path_free (path);
2757 }
2758}
2759
2760PlumaFileBrowserStoreResult
2761pluma_file_browser_store_set_virtual_root (PlumaFileBrowserStore * model,
2762 GtkTreeIter * iter)
2763{
2764 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_139
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_139 = 1; else _g_boolean_var_139 =
0; _g_boolean_var_139; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2765 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_139
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_139 = 1; else _g_boolean_var_139 =
0; _g_boolean_var_139; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2766 g_return_val_if_fail (iter != NULL,do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_140
; if (iter != ((void*)0)) _g_boolean_var_140 = 1; else _g_boolean_var_140
= 0; _g_boolean_var_140; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
(PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while (0)
2767 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_140
; if (iter != ((void*)0)) _g_boolean_var_140 = 1; else _g_boolean_var_140
= 0; _g_boolean_var_140; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
(PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while (0)
;
2768 g_return_val_if_fail (iter->user_data != NULL,do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_141
; if (iter->user_data != ((void*)0)) _g_boolean_var_141 = 1
; else _g_boolean_var_141 = 0; _g_boolean_var_141; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE
); } } while (0)
2769 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_141
; if (iter->user_data != ((void*)0)) _g_boolean_var_141 = 1
; else _g_boolean_var_141 = 0; _g_boolean_var_141; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE
); } } while (0)
;
2770
2771 model_clear (model, FALSE(0));
2772 set_virtual_root_from_node (model,
2773 (FileBrowserNode *) (iter->user_data));
2774
2775 return TRUE(!(0));
2776}
2777
2778PlumaFileBrowserStoreResult
2779pluma_file_browser_store_set_virtual_root_from_string
2780 (PlumaFileBrowserStore * model, gchar const *root) {
2781 GFile *file;
2782
2783 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_142
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_142 = 1; else _g_boolean_var_142 =
0; _g_boolean_var_142; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2784 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_142
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_142 = 1; else _g_boolean_var_142 =
0; _g_boolean_var_142; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2785
2786 file = g_file_new_for_uri (root);
2787 if (file == NULL((void*)0)) {
2788 g_warning ("Invalid uri (%s)", root);
2789 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2790 }
2791
2792 /* Check if uri is already the virtual root */
2793 if (model->priv->virtual_root &&
2794 g_file_equal (model->priv->virtual_root->file, file)) {
2795 g_object_unref (file);
2796 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2797 }
2798
2799 /* Check if uri is the root itself */
2800 if (g_file_equal (model->priv->root->file, file)) {
2801 g_object_unref (file);
2802
2803 /* Always clear the model before altering the nodes */
2804 model_clear (model, FALSE(0));
2805 set_virtual_root_from_node (model, model->priv->root);
2806 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2807 }
2808
2809 if (!g_file_has_prefix (file, model->priv->root->file)) {
2810 gchar *str, *str1;
2811
2812 str = g_file_get_parse_name (model->priv->root->file);
2813 str1 = g_file_get_parse_name (file);
2814
2815 g_warning
2816 ("Virtual root (%s) is not below actual root (%s)",
2817 str1, str);
2818
2819 g_free (str);
2820 g_free (str1);
2821
2822 g_object_unref (file);
2823 return PLUMA_FILE_BROWSER_STORE_RESULT_ERROR;
2824 }
2825
2826 set_virtual_root_from_file (model, file);
2827 g_object_unref (file);
2828
2829 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2830}
2831
2832PlumaFileBrowserStoreResult
2833pluma_file_browser_store_set_virtual_root_top (PlumaFileBrowserStore *
2834 model)
2835{
2836 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_143
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_143 = 1; else _g_boolean_var_143 =
0; _g_boolean_var_143; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2837 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_143
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_143 = 1; else _g_boolean_var_143 =
0; _g_boolean_var_143; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2838
2839 if (model->priv->virtual_root == model->priv->root)
2840 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2841
2842 model_clear (model, FALSE(0));
2843 set_virtual_root_from_node (model, model->priv->root);
2844
2845 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2846}
2847
2848PlumaFileBrowserStoreResult
2849pluma_file_browser_store_set_virtual_root_up (PlumaFileBrowserStore *
2850 model)
2851{
2852 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_144
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_144 = 1; else _g_boolean_var_144 =
0; _g_boolean_var_144; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2853 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_144
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_144 = 1; else _g_boolean_var_144 =
0; _g_boolean_var_144; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2854
2855 if (model->priv->virtual_root == model->priv->root)
2856 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2857
2858 model_clear (model, FALSE(0));
2859 set_virtual_root_from_node (model,
2860 model->priv->virtual_root->parent);
2861
2862 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2863}
2864
2865gboolean
2866pluma_file_browser_store_get_iter_virtual_root (PlumaFileBrowserStore *
2867 model, GtkTreeIter * iter)
2868{
2869 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_145
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_145 = 1; else _g_boolean_var_145 =
0; _g_boolean_var_145; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
2870 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_146
; if (iter != ((void*)0)) _g_boolean_var_146 = 1; else _g_boolean_var_146
= 0; _g_boolean_var_146; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
2871
2872 if (model->priv->virtual_root == NULL((void*)0))
2873 return FALSE(0);
2874
2875 iter->user_data = model->priv->virtual_root;
2876 return TRUE(!(0));
2877}
2878
2879gboolean
2880pluma_file_browser_store_get_iter_root (PlumaFileBrowserStore * model,
2881 GtkTreeIter * iter)
2882{
2883 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_147
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_147 = 1; else _g_boolean_var_147 =
0; _g_boolean_var_147; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
2884 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_148
; if (iter != ((void*)0)) _g_boolean_var_148 = 1; else _g_boolean_var_148
= 0; _g_boolean_var_148; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
2885
2886 if (model->priv->root == NULL((void*)0))
2887 return FALSE(0);
2888
2889 iter->user_data = model->priv->root;
2890 return TRUE(!(0));
2891}
2892
2893gboolean
2894pluma_file_browser_store_iter_equal (PlumaFileBrowserStore * model,
2895 GtkTreeIter * iter1,
2896 GtkTreeIter * iter2)
2897{
2898 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_149
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_149 = 1; else _g_boolean_var_149 =
0; _g_boolean_var_149; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
2899 g_return_val_if_fail (iter1 != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_150
; if (iter1 != ((void*)0)) _g_boolean_var_150 = 1; else _g_boolean_var_150
= 0; _g_boolean_var_150; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter1 != NULL");
return ((0)); } } while (0)
;
2900 g_return_val_if_fail (iter2 != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_151
; if (iter2 != ((void*)0)) _g_boolean_var_151 = 1; else _g_boolean_var_151
= 0; _g_boolean_var_151; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter2 != NULL");
return ((0)); } } while (0)
;
2901 g_return_val_if_fail (iter1->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_152
; if (iter1->user_data != ((void*)0)) _g_boolean_var_152 =
1; else _g_boolean_var_152 = 0; _g_boolean_var_152; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter1->user_data != NULL"); return ((0));
} } while (0)
;
2902 g_return_val_if_fail (iter2->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_153
; if (iter2->user_data != ((void*)0)) _g_boolean_var_153 =
1; else _g_boolean_var_153 = 0; _g_boolean_var_153; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter2->user_data != NULL"); return ((0));
} } while (0)
;
2903
2904 return (iter1->user_data == iter2->user_data);
2905}
2906
2907void
2908pluma_file_browser_store_cancel_mount_operation (PlumaFileBrowserStore *store)
2909{
2910 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (store))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_154
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((store)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_154 = 1; else _g_boolean_var_154 =
0; _g_boolean_var_154; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (store)"
); return; } } while (0)
;
2911
2912 cancel_mount_operation (store);
2913}
2914
2915PlumaFileBrowserStoreResult
2916pluma_file_browser_store_set_root_and_virtual_root (PlumaFileBrowserStore *
2917 model,
2918 gchar const *root,
2919 gchar const *virtual_root)
2920{
2921 GFile * file = NULL((void*)0);
2922 GFile * vfile = NULL((void*)0);
2923 FileBrowserNode * node;
2924 gboolean equal = FALSE(0);
2925
2926 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_155
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_155 = 1; else _g_boolean_var_155 =
0; _g_boolean_var_155; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2927 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_155
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_155 = 1; else _g_boolean_var_155 =
0; _g_boolean_var_155; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2928
2929 if (root == NULL((void*)0) && model->priv->root == NULL((void*)0))
2930 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2931
2932 if (root != NULL((void*)0)) {
2933 file = g_file_new_for_uri (root);
2934 }
2935
2936 if (root != NULL((void*)0) && model->priv->root != NULL((void*)0)) {
2937 equal = g_file_equal (file, model->priv->root->file);
2938
2939 if (equal && virtual_root == NULL((void*)0)) {
2940 g_object_unref (file);
2941 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2942 }
2943 }
2944
2945 if (virtual_root) {
2946 vfile = g_file_new_for_uri (virtual_root);
2947
2948 if (equal && g_file_equal (vfile, model->priv->virtual_root->file)) {
2949 if (file)
2950 g_object_unref (file);
2951
2952 g_object_unref (vfile);
2953 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2954 }
2955
2956 g_object_unref (vfile);
2957 }
2958
2959 /* make sure to cancel any previous mount operations */
2960 cancel_mount_operation (model);
2961
2962 /* Always clear the model before altering the nodes */
2963 model_clear (model, TRUE(!(0)));
2964 file_browser_node_free (model, model->priv->root);
2965
2966 model->priv->root = NULL((void*)0);
2967 model->priv->virtual_root = NULL((void*)0);
2968
2969 if (file != NULL((void*)0)) {
2970 /* Create the root node */
2971 node = file_browser_node_dir_new (model, file, NULL((void*)0));
2972
2973 g_object_unref (file);
2974
2975 model->priv->root = node;
2976 return model_mount_root (model, virtual_root);
2977 } else {
2978 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "root");
2979 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "virtual-root");
2980 }
2981
2982 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2983}
2984
2985PlumaFileBrowserStoreResult
2986pluma_file_browser_store_set_root (PlumaFileBrowserStore * model,
2987 gchar const *root)
2988{
2989 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_156
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_156 = 1; else _g_boolean_var_156 =
0; _g_boolean_var_156; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2990 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_156
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_156 = 1; else _g_boolean_var_156 =
0; _g_boolean_var_156; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2991 return pluma_file_browser_store_set_root_and_virtual_root (model,
2992 root,
2993 NULL((void*)0));
2994}
2995
2996gchar *
2997pluma_file_browser_store_get_root (PlumaFileBrowserStore * model)
2998{
2999 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_157
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_157 = 1; else _g_boolean_var_157 =
0; _g_boolean_var_157; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (((void*)0)); } } while (0)
;
3000
3001 if (model->priv->root == NULL((void*)0) || model->priv->root->file == NULL((void*)0))
3002 return NULL((void*)0);
3003 else
3004 return g_file_get_uri (model->priv->root->file);
3005}
3006
3007gchar *
3008pluma_file_browser_store_get_virtual_root (PlumaFileBrowserStore * model)
3009{
3010 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_158
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_158 = 1; else _g_boolean_var_158 =
0; _g_boolean_var_158; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (((void*)0)); } } while (0)
;
3011
3012 if (model->priv->virtual_root == NULL((void*)0) || model->priv->virtual_root->file == NULL((void*)0))
3013 return NULL((void*)0);
3014 else
3015 return g_file_get_uri (model->priv->virtual_root->file);
3016}
3017
3018void
3019_pluma_file_browser_store_iter_expanded (PlumaFileBrowserStore * model,
3020 GtkTreeIter * iter)
3021{
3022 FileBrowserNode *node;
3023
3024 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_159
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_159 = 1; else _g_boolean_var_159 =
0; _g_boolean_var_159; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return; } } while (0)
;
3025 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_160
; if (iter != ((void*)0)) _g_boolean_var_160 = 1; else _g_boolean_var_160
= 0; _g_boolean_var_160; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
3026 g_return_if_fail (iter->user_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_161
; if (iter->user_data != ((void*)0)) _g_boolean_var_161 = 1
; else _g_boolean_var_161 = 0; _g_boolean_var_161; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return; } } while
(0)
;
3027
3028 node = (FileBrowserNode *) (iter->user_data);
3029
3030 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
&& !NODE_LOADED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
) {
3031 /* Load it now */
3032 model_load_directory (model, node);
3033 }
3034}
3035
3036void
3037_pluma_file_browser_store_iter_collapsed (PlumaFileBrowserStore * model,
3038 GtkTreeIter * iter)
3039{
3040 FileBrowserNode *node;
3041 GSList *item;
3042
3043 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_162
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_162 = 1; else _g_boolean_var_162 =
0; _g_boolean_var_162; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return; } } while (0)
;
3044 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_163
; if (iter != ((void*)0)) _g_boolean_var_163 = 1; else _g_boolean_var_163
= 0; _g_boolean_var_163; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
3045 g_return_if_fail (iter->user_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_164
; if (iter->user_data != ((void*)0)) _g_boolean_var_164 = 1
; else _g_boolean_var_164 = 0; _g_boolean_var_164; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return; } } while
(0)
;
3046
3047 node = (FileBrowserNode *) (iter->user_data);
3048
3049 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
&& NODE_LOADED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
) {
3050 /* Unload children of the children, keeping 1 depth in cache */
3051
3052 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item;
3053 item = item->next) {
3054 node = (FileBrowserNode *) (item->data);
3055
3056 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
&& NODE_LOADED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
) {
3057 file_browser_node_unload (model, node,
3058 TRUE(!(0)));
3059 model_check_dummy (model, node);
3060 }
3061 }
3062 }
3063}
3064
3065PlumaFileBrowserStoreFilterMode
3066pluma_file_browser_store_get_filter_mode (PlumaFileBrowserStore * model)
3067{
3068 return model->priv->filter_mode;
3069}
3070
3071void
3072pluma_file_browser_store_set_filter_mode (PlumaFileBrowserStore * model,
3073 PlumaFileBrowserStoreFilterMode
3074 mode)
3075{
3076 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_165
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_165 = 1; else _g_boolean_var_165 =
0; _g_boolean_var_165; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return; } } while (0)
;
3077
3078 if (model->priv->filter_mode == mode)
3079 return;
3080
3081 model->priv->filter_mode = mode;
3082 model_refilter (model);
3083
3084 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "filter-mode");
3085}
3086
3087void
3088pluma_file_browser_store_set_filter_func (PlumaFileBrowserStore * model,
3089 PlumaFileBrowserStoreFilterFunc
3090 func, gpointer user_data)
3091{
3092 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_166
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_166 = 1; else _g_boolean_var_166 =
0; _g_boolean_var_166; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return; } } while (0)
;
3093
3094 model->priv->filter_func = func;
3095 model->priv->filter_user_data = user_data;
3096 model_refilter (model);
3097}
3098
3099void
3100pluma_file_browser_store_refilter (PlumaFileBrowserStore * model)
3101{
3102 model_refilter (model);
3103}
3104
3105PlumaFileBrowserStoreFilterMode
3106pluma_file_browser_store_filter_mode_get_default (void)
3107{
3108 return PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_HIDDEN;
3109}
3110
3111void
3112pluma_file_browser_store_refresh (PlumaFileBrowserStore * model)
3113{
3114 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_167
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_167 = 1; else _g_boolean_var_167 =
0; _g_boolean_var_167; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return; } } while (0)
;
3115
3116 if (model->priv->root == NULL((void*)0) || model->priv->virtual_root == NULL((void*)0))
3117 return;
3118
3119 /* Clear the model */
3120 g_signal_emit (model, model_signals[BEGIN_REFRESH], 0);
3121 file_browser_node_unload (model, model->priv->virtual_root, TRUE(!(0)));
3122 model_load_directory (model, model->priv->virtual_root);
3123 g_signal_emit (model, model_signals[END_REFRESH], 0);
3124}
3125
3126static void
3127reparent_node (FileBrowserNode * node, gboolean reparent)
3128{
3129 FileBrowserNodeDir * dir;
3130 GSList * child;
3131 GFile * parent;
3132 gchar * base;
3133
3134 if (!node->file) {
3135 return;
3136 }
3137
3138 if (reparent) {
3139 parent = node->parent->file;
3140 base = g_file_get_basename (node->file);
3141 g_object_unref (node->file);
3142
3143 node->file = g_file_get_child (parent, base);
3144 g_free (base);
3145 }
3146
3147 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
3148 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
3149
3150 for (child = dir->children; child; child = child->next) {
3151 reparent_node ((FileBrowserNode *)child->data, TRUE(!(0)));
3152 }
3153 }
3154}
3155
3156gboolean
3157pluma_file_browser_store_rename (PlumaFileBrowserStore * model,
3158 GtkTreeIter * iter,
3159 const gchar * new_name,
3160 GError ** error)
3161{
3162 FileBrowserNode *node;
3163 GFile * file;
3164 GFile * parent;
3165 GFile * previous;
3166 GError * err = NULL((void*)0);
3167 gchar * olduri;
3168 gchar * newuri;
3169 GtkTreePath *path;
3170
3171 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_168
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_168 = 1; else _g_boolean_var_168 =
0; _g_boolean_var_168; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
3172 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_169
; if (iter != ((void*)0)) _g_boolean_var_169 = 1; else _g_boolean_var_169
= 0; _g_boolean_var_169; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
3173 g_return_val_if_fail (iter->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_170
; if (iter->user_data != ((void*)0)) _g_boolean_var_170 = 1
; else _g_boolean_var_170 = 0; _g_boolean_var_170; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return ((0)); }
} while (0)
;
3174
3175 node = (FileBrowserNode *) (iter->user_data);
3176
3177 parent = g_file_get_parent (node->file);
3178 g_return_val_if_fail (parent != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_171
; if (parent != ((void*)0)) _g_boolean_var_171 = 1; else _g_boolean_var_171
= 0; _g_boolean_var_171; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "parent != NULL")
; return ((0)); } } while (0)
;
3179
3180 file = g_file_get_child (parent, new_name);
3181 g_object_unref (parent);
3182
3183 if (g_file_equal (node->file, file)) {
3184 g_object_unref (file);
3185 return TRUE(!(0));
3186 }
3187
3188 if (g_file_move (node->file, file, G_FILE_COPY_NONE, NULL((void*)0), NULL((void*)0), NULL((void*)0), &err)) {
3189 previous = node->file;
3190 node->file = file;
3191
3192 /* This makes sure the actual info for the node is requeried */
3193 file_browser_node_set_name (node);
3194 file_browser_node_set_from_info (model, node, NULL((void*)0), TRUE(!(0)));
3195
3196 reparent_node (node, FALSE(0));
3197
3198 if (model_node_visibility (model, node)) {
3199 path = pluma_file_browser_store_get_path_real (model, node);
3200 row_changed (model, &path, iter);
3201 gtk_tree_path_free (path);
3202
3203 /* Reorder this item */
3204 model_resort_node (model, node);
3205 } else {
3206 g_object_unref (previous);
3207
3208 if (error != NULL((void*)0))
3209 *error = g_error_new_literal (pluma_file_browser_store_error_quark (),
3210 PLUMA_FILE_BROWSER_ERROR_RENAME,
3211 _("The renamed file is currently filtered out. You need to adjust your filter settings to make the file visible")((char *) g_dgettext ("pluma", "The renamed file is currently filtered out. You need to adjust your filter settings to make the file visible"
))
);
3212 return FALSE(0);
3213 }
3214
3215 olduri = g_file_get_uri (previous);
3216 newuri = g_file_get_uri (node->file);
3217
3218 g_signal_emit (model, model_signals[RENAME], 0, olduri, newuri);
3219
3220 g_object_unref (previous);
3221 g_free (olduri);
3222 g_free (newuri);
3223
3224 return TRUE(!(0));
3225 } else {
3226 g_object_unref (file);
3227
3228 if (err) {
3229 if (error != NULL((void*)0)) {
3230 *error =
3231 g_error_new_literal
3232 (pluma_file_browser_store_error_quark (),
3233 PLUMA_FILE_BROWSER_ERROR_RENAME,
3234 err->message);
3235 }
3236
3237 g_error_free (err);
3238 }
3239
3240 return FALSE(0);
3241 }
3242}
3243
3244static void
3245async_data_free (AsyncData * data)
3246{
3247 g_object_unref (data->cancellable);
3248
3249 g_list_free_full (data->files, g_object_unref);
3250
3251 if (!data->removed)
3252 data->model->priv->async_handles = g_slist_remove (data->model->priv->async_handles, data);
3253
3254 g_free (data);
3255}
3256
3257static gboolean
3258emit_no_trash (AsyncData * data)
3259{
3260 /* Emit the no trash error */
3261 gboolean ret;
3262
3263 g_signal_emit (data->model, model_signals[NO_TRASH], 0, data->files, &ret);
3264 return ret;
3265}
3266
3267static void
3268delete_file_finished (GFile *file,
3269 GAsyncResult *res,
3270 AsyncData *data)
3271{
3272 GError * error = NULL((void*)0);
3273 gboolean ok;
3274
3275 if (data->trash)
3276 {
3277 ok = g_file_trash_finish (file, res, &error);
3278 }
3279 else
3280 {
3281 ok = g_file_delete_finish (file, res, &error);
3282 }
3283
3284 if (ok)
3285 {
3286 /* Remove the file from the model */
3287 FileBrowserNode *node = model_find_node (data->model, NULL((void*)0), file);
3288
3289 if (node != NULL((void*)0))
3290 {
3291 model_remove_node (data->model, node, NULL((void*)0), TRUE(!(0)));
3292 }
3293
3294 /* Process the next file */
3295 data->iter = data->iter->next;
3296 }
3297 else if (!ok && error != NULL((void*)0))
3298 {
3299 gint code = error->code;
3300 g_error_free (error);
3301
3302 if (data->trash && code == G_IO_ERROR_NOT_SUPPORTED) {
3303 /* Trash is not supported on this system. Ask the user
3304 * if he wants to delete completely the files instead.
3305 */
3306 if (emit_no_trash (data))
3307 {
3308 /* Changes this into a delete job */
3309 data->trash = FALSE(0);
3310 data->iter = data->files;
3311 }
3312 else
3313 {
3314 /* End the job */
3315 async_data_free (data);
3316 return;
3317 }
3318 }
3319 else if (code == G_IO_ERROR_CANCELLED)
3320 {
3321 /* Job has been cancelled, end the job */
3322 async_data_free (data);
3323 return;
3324 }
3325 }
3326
3327 /* Continue the job */
3328 delete_files (data);
3329}
3330
3331static void
3332delete_files (AsyncData *data)
3333{
3334 GFile *file;
3335
3336 /* Check if our job is done */
3337 if (data->iter == NULL((void*)0))
3338 {
3339 async_data_free (data);
3340 return;
3341 }
3342
3343 file = G_FILE (data->iter->data)((((GFile*) (void *) ((data->iter->data)))));
3344
3345 if (data->trash)
3346 {
3347 g_file_trash_async (file,
3348 G_PRIORITY_DEFAULT0,
3349 data->cancellable,
3350 (GAsyncReadyCallback)delete_file_finished,
3351 data);
3352 }
3353 else
3354 {
3355 g_file_delete_async (file,
3356 G_PRIORITY_DEFAULT0,
3357 data->cancellable,
3358 (GAsyncReadyCallback)delete_file_finished,
3359 data);
3360 }
3361}
3362
3363PlumaFileBrowserStoreResult
3364pluma_file_browser_store_delete_all (PlumaFileBrowserStore *model,
3365 GList *rows, gboolean trash)
3366{
3367 FileBrowserNode * node;
3368 AsyncData * data;
3369 GList * files = NULL((void*)0);
3370 GList * row;
3371 GtkTreeIter iter;
3372 GtkTreePath * prev = NULL((void*)0);
3373 GtkTreePath * path;
3374
3375 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_172
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_172 = 1; else _g_boolean_var_172 =
0; _g_boolean_var_172; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
3376
3377 if (rows == NULL((void*)0))
3378 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
3379
3380 /* First we sort the paths so that we can later on remove any
3381 files/directories that are actually subfiles/directories of
3382 a directory that's also deleted */
3383 rows = g_list_sort (g_list_copy (rows), (GCompareFunc)gtk_tree_path_compare);
3384
3385 for (row = rows; row; row = row->next) {
3386 path = (GtkTreePath *)(row->data);
3387
3388 if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (model)((((GtkTreeModel*) (void *) ((model))))), &iter, path))
3389 continue;
3390
3391 /* Skip if the current path is actually a descendant of the
3392 previous path */
3393 if (prev != NULL((void*)0) && gtk_tree_path_is_descendant (path, prev))
3394 continue;
3395
3396 prev = path;
3397 node = (FileBrowserNode *)(iter.user_data);
3398 files = g_list_prepend (files, g_object_ref (node->file)((__typeof__ (node->file)) (g_object_ref) (node->file)));
3399 }
3400
3401 data = g_new (AsyncData, 1)(AsyncData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (AsyncData); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
3402
3403 data->model = model;
3404 data->cancellable = g_cancellable_new ();
3405 data->files = files;
3406 data->trash = trash;
3407 data->iter = files;
3408 data->removed = FALSE(0);
3409
3410 model->priv->async_handles =
3411 g_slist_prepend (model->priv->async_handles, data);
3412
3413 delete_files (data);
3414 g_list_free (rows);
3415
3416 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
3417}
3418
3419PlumaFileBrowserStoreResult
3420pluma_file_browser_store_delete (PlumaFileBrowserStore * model,
3421 GtkTreeIter * iter, gboolean trash)
3422{
3423 FileBrowserNode *node;
3424 GList *rows = NULL((void*)0);
3425 PlumaFileBrowserStoreResult result;
3426
3427 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_173
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_173 = 1; else _g_boolean_var_173 =
0; _g_boolean_var_173; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
3428 g_return_val_if_fail (iter != NULL, PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_174
; if (iter != ((void*)0)) _g_boolean_var_174 = 1; else _g_boolean_var_174
= 0; _g_boolean_var_174; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
(PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while (0)
;
3429 g_return_val_if_fail (iter->user_data != NULL, PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_175
; if (iter->user_data != ((void*)0)) _g_boolean_var_175 = 1
; else _g_boolean_var_175 = 0; _g_boolean_var_175; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE
); } } while (0)
;
3430
3431 node = (FileBrowserNode *) (iter->user_data);
3432
3433 if (NODE_IS_DUMMY (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
)
3434 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
3435
3436 rows = g_list_append(NULL((void*)0), pluma_file_browser_store_get_path_real (model, node));
3437 result = pluma_file_browser_store_delete_all (model, rows, trash);
3438
3439 g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free);
3440
3441 return result;
3442}
3443
3444gboolean
3445pluma_file_browser_store_new_file (PlumaFileBrowserStore * model,
3446 GtkTreeIter * parent,
3447 GtkTreeIter * iter)
3448{
3449 GFile * file;
3450 GFileOutputStream * stream;
3451 FileBrowserNodeDir *parent_node;
3452 gboolean result = FALSE(0);
3453 FileBrowserNode *node;
3454 GError * error = NULL((void*)0);
3455
3456 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_176
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_176 = 1; else _g_boolean_var_176 =
0; _g_boolean_var_176; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
3457 g_return_val_if_fail (parent != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_177
; if (parent != ((void*)0)) _g_boolean_var_177 = 1; else _g_boolean_var_177
= 0; _g_boolean_var_177; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "parent != NULL")
; return ((0)); } } while (0)
;
3458 g_return_val_if_fail (parent->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_178
; if (parent->user_data != ((void*)0)) _g_boolean_var_178 =
1; else _g_boolean_var_178 = 0; _g_boolean_var_178; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "parent->user_data != NULL"); return ((0))
; } } while (0)
;
3459 g_return_val_if_fail (NODE_IS_DIRdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_179
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_179
= 1; else _g_boolean_var_179 = 0; _g_boolean_var_179; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
3460 ((FileBrowserNode *) (parent->user_data)),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_179
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_179
= 1; else _g_boolean_var_179 = 0; _g_boolean_var_179; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
3461 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_179
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_179
= 1; else _g_boolean_var_179 = 0; _g_boolean_var_179; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
;
3462 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_180
; if (iter != ((void*)0)) _g_boolean_var_180 = 1; else _g_boolean_var_180
= 0; _g_boolean_var_180; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
3463
3464 parent_node = FILE_BROWSER_NODE_DIR (parent->user_data)((FileBrowserNodeDir *)(parent->user_data));
3465 /* Translators: This is the default name of new files created by the file browser pane. */
3466 file = unique_new_name (((FileBrowserNode *) parent_node)->file, _("file")((char *) g_dgettext ("pluma", "file")));
3467
3468 stream = g_file_create (file, G_FILE_CREATE_NONE, NULL((void*)0), &error);
3469
3470 if (!stream)
3471 {
3472 g_signal_emit (model, model_signals[ERROR], 0,
3473 PLUMA_FILE_BROWSER_ERROR_NEW_FILE,
3474 error->message);
3475 g_error_free (error);
3476 } else {
3477 g_object_unref (stream);
3478 node = model_add_node_from_file (model,
3479 (FileBrowserNode *)parent_node,
3480 file,
3481 NULL((void*)0));
3482
3483 if (model_node_visibility (model, node)) {
3484 iter->user_data = node;
3485 result = TRUE(!(0));
3486 } else {
3487 g_signal_emit (model, model_signals[ERROR], 0,
3488 PLUMA_FILE_BROWSER_ERROR_NEW_FILE,
3489 _((char *) g_dgettext ("pluma", "The new file is currently filtered out. You need to adjust your filter settings to make the file visible"
))
3490 ("The new file is currently filtered out. You need to adjust your filter settings to make the file visible")((char *) g_dgettext ("pluma", "The new file is currently filtered out. You need to adjust your filter settings to make the file visible"
))
);
3491 }
3492 }
3493
3494 g_object_unref (file);
3495 return result;
3496}
3497
3498gboolean
3499pluma_file_browser_store_new_directory (PlumaFileBrowserStore * model,
3500 GtkTreeIter * parent,
3501 GtkTreeIter * iter)
3502{
3503 GFile * file;
3504 FileBrowserNodeDir *parent_node;
3505 GError * error = NULL((void*)0);
3506 FileBrowserNode *node;
3507 gboolean result = FALSE(0);
3508
3509 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_181
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_181 = 1; else _g_boolean_var_181 =
0; _g_boolean_var_181; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
3510 g_return_val_if_fail (parent != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_182
; if (parent != ((void*)0)) _g_boolean_var_182 = 1; else _g_boolean_var_182
= 0; _g_boolean_var_182; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "parent != NULL")
; return ((0)); } } while (0)
;
3511 g_return_val_if_fail (parent->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_183
; if (parent->user_data != ((void*)0)) _g_boolean_var_183 =
1; else _g_boolean_var_183 = 0; _g_boolean_var_183; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "parent->user_data != NULL"); return ((0))
; } } while (0)
;
3512 g_return_val_if_fail (NODE_IS_DIRdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_184
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_184
= 1; else _g_boolean_var_184 = 0; _g_boolean_var_184; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
3513 ((FileBrowserNode *) (parent->user_data)),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_184
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_184
= 1; else _g_boolean_var_184 = 0; _g_boolean_var_184; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
3514 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_184
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_184
= 1; else _g_boolean_var_184 = 0; _g_boolean_var_184; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
;
3515 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_185
; if (iter != ((void*)0)) _g_boolean_var_185 = 1; else _g_boolean_var_185
= 0; _g_boolean_var_185; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
3516
3517 parent_node = FILE_BROWSER_NODE_DIR (parent->user_data)((FileBrowserNodeDir *)(parent->user_data));
3518 /* Translators: This is the default name of new directories created by the file browser pane. */
3519 file = unique_new_name (((FileBrowserNode *) parent_node)->file, _("directory")((char *) g_dgettext ("pluma", "directory")));
3520
3521 if (!g_file_make_directory (file, NULL((void*)0), &error)) {
3522 g_signal_emit (model, model_signals[ERROR], 0,
3523 PLUMA_FILE_BROWSER_ERROR_NEW_DIRECTORY,
3524 error->message);
3525 g_error_free (error);
3526 } else {
3527 node = model_add_node_from_file (model,
3528 (FileBrowserNode *)parent_node,
3529 file,
3530 NULL((void*)0));
3531
3532 if (model_node_visibility (model, node)) {
3533 iter->user_data = node;
3534 result = TRUE(!(0));
3535 } else {
3536 g_signal_emit (model, model_signals[ERROR], 0,
3537 PLUMA_FILE_BROWSER_ERROR_NEW_FILE,
3538 _((char *) g_dgettext ("pluma", "The new directory is currently filtered out. You need to adjust your filter settings to make the directory visible"
))
3539 ("The new directory is currently filtered out. You need to adjust your filter settings to make the directory visible")((char *) g_dgettext ("pluma", "The new directory is currently filtered out. You need to adjust your filter settings to make the directory visible"
))
);
3540 }
3541 }
3542
3543 g_object_unref (file);
3544 return result;
3545}
3546
3547void
3548_pluma_file_browser_store_register_type (GTypeModule *type_module)
3549{
3550 pluma_file_browser_store_register_type (type_module);
3551}
3552
3553// ex:ts=8:noet:
diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-527848.html b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-527848.html new file mode 100644 index 00000000..db960d11 --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-527848.html @@ -0,0 +1,1327 @@ + + + +plumatextregion.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:pluma/plumatextregion.c
Warning:line 332, column 4
Value stored to 'start_node' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name plumatextregion.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/pluma -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I .. -I . -I ./mate-submodules/libegg -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/gtksourceview-4 -I /usr/include/libpeas-1.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D DATADIR="/usr/local/share" -D PLUMA_DATADIR="/usr/local/share/pluma" -D PLUMA_LOCALEDIR="/usr/local/share/locale/" -D LIBDIR="/usr/local/lib" -D PLUMA_LIBDIR="/usr/local/lib/pluma" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/pluma -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-10-22-114445-13211-1 -x c plumatextregion.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2 *
3 * plumatextregion.h - GtkTextMark based region utility functions
4 *
5 * This file is part of the GtkSourceView widget
6 *
7 * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez@gmx.net>
8 * Copyright (C) 2012-2021 MATE Developers
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
24 */
25
26#ifdef HAVE_CONFIG_H1
27#include <config.h>
28#endif
29
30#include <glib.h>
31
32#include "plumatextregion.h"
33
34
35#undef ENABLE_DEBUG
36/*
37#define ENABLE_DEBUG
38*/
39
40#ifdef ENABLE_DEBUG
41#define DEBUG(x) (x)
42#else
43#define DEBUG(x)
44#endif
45
46typedef struct _Subregion {
47 GtkTextMark *start;
48 GtkTextMark *end;
49} Subregion;
50
51struct _PlumaTextRegion {
52 GtkTextBuffer *buffer;
53 GList *subregions;
54 guint32 time_stamp;
55};
56
57typedef struct _PlumaTextRegionIteratorReal PlumaTextRegionIteratorReal;
58
59struct _PlumaTextRegionIteratorReal {
60 PlumaTextRegion *region;
61 guint32 region_time_stamp;
62
63 GList *subregions;
64};
65
66
67/* ----------------------------------------------------------------------
68 Private interface
69 ---------------------------------------------------------------------- */
70
71/* Find and return a subregion node which contains the given text
72 iter. If left_side is TRUE, return the subregion which contains
73 the text iter or which is the leftmost; else return the rightmost
74 subregion */
75static GList *
76find_nearest_subregion (PlumaTextRegion *region,
77 const GtkTextIter *iter,
78 GList *begin,
79 gboolean leftmost,
80 gboolean include_edges)
81{
82 GList *l, *retval;
83
84 g_return_val_if_fail (region != NULL && iter != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_52
; if (region != ((void*)0) && iter != ((void*)0)) _g_boolean_var_52
= 1; else _g_boolean_var_52 = 0; _g_boolean_var_52; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "region != NULL && iter != NULL"); return
(((void*)0)); } } while (0)
;
85
86 if (!begin)
87 begin = region->subregions;
88
89 if (begin)
90 retval = begin->prev;
91 else
92 retval = NULL((void*)0);
93
94 for (l = begin; l; l = l->next) {
95 GtkTextIter sr_iter;
96 Subregion *sr = l->data;
97 gint cmp;
98
99 if (!leftmost) {
100 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_iter, sr->end);
101 cmp = gtk_text_iter_compare (iter, &sr_iter);
102 if (cmp < 0 || (cmp == 0 && include_edges)) {
103 retval = l;
104 break;
105 }
106
107 } else {
108 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_iter, sr->start);
109 cmp = gtk_text_iter_compare (iter, &sr_iter);
110 if (cmp > 0 || (cmp == 0 && include_edges))
111 retval = l;
112 else
113 break;
114 }
115 }
116 return retval;
117}
118
119/* ----------------------------------------------------------------------
120 Public interface
121 ---------------------------------------------------------------------- */
122
123PlumaTextRegion *
124pluma_text_region_new (GtkTextBuffer *buffer)
125{
126 PlumaTextRegion *region;
127
128 g_return_val_if_fail (buffer != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_53
; if (buffer != ((void*)0)) _g_boolean_var_53 = 1; else _g_boolean_var_53
= 0; _g_boolean_var_53; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "buffer != NULL")
; return (((void*)0)); } } while (0)
;
129
130 region = g_new (PlumaTextRegion, 1)(PlumaTextRegion *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (PlumaTextRegion); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
131 region->buffer = buffer;
132 region->subregions = NULL((void*)0);
133 region->time_stamp = 0;
134
135 return region;
136}
137
138void
139pluma_text_region_destroy (PlumaTextRegion *region, gboolean delete_marks)
140{
141 g_return_if_fail (region != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_54
; if (region != ((void*)0)) _g_boolean_var_54 = 1; else _g_boolean_var_54
= 0; _g_boolean_var_54; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return; } } while (0)
;
142
143 while (region->subregions) {
144 Subregion *sr = region->subregions->data;
145 if (delete_marks) {
146 gtk_text_buffer_delete_mark (region->buffer, sr->start);
147 gtk_text_buffer_delete_mark (region->buffer, sr->end);
148 }
149 g_free (sr);
150 region->subregions = g_list_delete_link (region->subregions,
151 region->subregions);
152 }
153 region->buffer = NULL((void*)0);
154 region->time_stamp = 0;
155
156 g_free (region);
157}
158
159GtkTextBuffer *
160pluma_text_region_get_buffer (PlumaTextRegion *region)
161{
162 g_return_val_if_fail (region != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_55
; if (region != ((void*)0)) _g_boolean_var_55 = 1; else _g_boolean_var_55
= 0; _g_boolean_var_55; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return (((void*)0)); } } while (0)
;
163
164 return region->buffer;
165}
166
167static void
168pluma_text_region_clear_zero_length_subregions (PlumaTextRegion *region)
169{
170 GtkTextIter start, end;
171 GList *node;
172
173 g_return_if_fail (region != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_56
; if (region != ((void*)0)) _g_boolean_var_56 = 1; else _g_boolean_var_56
= 0; _g_boolean_var_56; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return; } } while (0)
;
174
175 for (node = region->subregions; node; ) {
176 Subregion *sr = node->data;
177 gtk_text_buffer_get_iter_at_mark (region->buffer, &start, sr->start);
178 gtk_text_buffer_get_iter_at_mark (region->buffer, &end, sr->end);
179 if (gtk_text_iter_equal (&start, &end)) {
180 gtk_text_buffer_delete_mark (region->buffer, sr->start);
181 gtk_text_buffer_delete_mark (region->buffer, sr->end);
182 g_free (sr);
183 if (node == region->subregions)
184 region->subregions = node = g_list_delete_link (node, node);
185 else
186 node = g_list_delete_link (node, node);
187
188 ++region->time_stamp;
189
190 } else {
191 node = node->next;
192 }
193 }
194}
195
196void
197pluma_text_region_add (PlumaTextRegion *region,
198 const GtkTextIter *_start,
199 const GtkTextIter *_end)
200{
201 GList *start_node, *end_node;
202 GtkTextIter start, end;
203
204 g_return_if_fail (region != NULL && _start != NULL && _end != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_57
; if (region != ((void*)0) && _start != ((void*)0) &&
_end != ((void*)0)) _g_boolean_var_57 = 1; else _g_boolean_var_57
= 0; _g_boolean_var_57; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL && _start != NULL && _end != NULL"
); return; } } while (0)
;
205
206 start = *_start;
207 end = *_end;
208
209 DEBUG (g_print ("---\n"));
210 DEBUG (pluma_text_region_debug_print (region));
211 DEBUG (g_message ("region_add (%d, %d)",
212 gtk_text_iter_get_offset (&start),
213 gtk_text_iter_get_offset (&end)));
214
215 gtk_text_iter_order (&start, &end);
216
217 /* don't add zero-length regions */
218 if (gtk_text_iter_equal (&start, &end))
219 return;
220
221 /* find bounding subregions */
222 start_node = find_nearest_subregion (region, &start, NULL((void*)0), FALSE(0), TRUE(!(0)));
223 end_node = find_nearest_subregion (region, &end, start_node, TRUE(!(0)), TRUE(!(0)));
224
225 if (start_node == NULL((void*)0) || end_node == NULL((void*)0) || end_node == start_node->prev) {
226 /* create the new subregion */
227 Subregion *sr = g_new0 (Subregion, 1)(Subregion *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (Subregion); gpointer __p; if (__s == 1) __p = g_malloc0
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s); __p
; }))
;
228 sr->start = gtk_text_buffer_create_mark (region->buffer, NULL((void*)0), &start, TRUE(!(0)));
229 sr->end = gtk_text_buffer_create_mark (region->buffer, NULL((void*)0), &end, FALSE(0));
230
231 if (start_node == NULL((void*)0)) {
232 /* append the new region */
233 region->subregions = g_list_append (region->subregions, sr);
234
235 } else if (end_node == NULL((void*)0)) {
236 /* prepend the new region */
237 region->subregions = g_list_prepend (region->subregions, sr);
238
239 } else {
240 /* we are in the middle of two subregions */
241 region->subregions = g_list_insert_before (region->subregions,
242 start_node, sr);
243 }
244 }
245 else {
246 GtkTextIter iter;
247 Subregion *sr = start_node->data;
248 if (start_node != end_node) {
249 /* we need to merge some subregions */
250 GList *l = start_node->next;
251 Subregion *q;
252
253 gtk_text_buffer_delete_mark (region->buffer, sr->end);
254 while (l != end_node) {
255 q = l->data;
256 gtk_text_buffer_delete_mark (region->buffer, q->start);
257 gtk_text_buffer_delete_mark (region->buffer, q->end);
258 g_free (q);
259 l = g_list_delete_link (l, l);
260 }
261 q = l->data;
262 gtk_text_buffer_delete_mark (region->buffer, q->start);
263 sr->end = q->end;
264 g_free (q);
265 l = g_list_delete_link (l, l);
266 }
267 /* now move marks if that action expands the region */
268 gtk_text_buffer_get_iter_at_mark (region->buffer, &iter, sr->start);
269 if (gtk_text_iter_compare (&iter, &start) > 0)
270 gtk_text_buffer_move_mark (region->buffer, sr->start, &start);
271 gtk_text_buffer_get_iter_at_mark (region->buffer, &iter, sr->end);
272 if (gtk_text_iter_compare (&iter, &end) < 0)
273 gtk_text_buffer_move_mark (region->buffer, sr->end, &end);
274 }
275
276 ++region->time_stamp;
277
278 DEBUG (pluma_text_region_debug_print (region));
279}
280
281void
282pluma_text_region_subtract (PlumaTextRegion *region,
283 const GtkTextIter *_start,
284 const GtkTextIter *_end)
285{
286 GList *start_node, *end_node, *node;
287 GtkTextIter sr_start_iter, sr_end_iter;
288 gboolean done;
289 gboolean start_is_outside, end_is_outside;
290 Subregion *sr;
291 GtkTextIter start, end;
292
293 g_return_if_fail (region != NULL && _start != NULL && _end != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_58
; if (region != ((void*)0) && _start != ((void*)0) &&
_end != ((void*)0)) _g_boolean_var_58 = 1; else _g_boolean_var_58
= 0; _g_boolean_var_58; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL && _start != NULL && _end != NULL"
); return; } } while (0)
;
294
295 start = *_start;
296 end = *_end;
297
298 DEBUG (g_print ("---\n"));
299 DEBUG (pluma_text_region_debug_print (region));
300 DEBUG (g_message ("region_substract (%d, %d)",
301 gtk_text_iter_get_offset (&start),
302 gtk_text_iter_get_offset (&end)));
303
304 gtk_text_iter_order (&start, &end);
305
306 /* find bounding subregions */
307 start_node = find_nearest_subregion (region, &start, NULL((void*)0), FALSE(0), FALSE(0));
308 end_node = find_nearest_subregion (region, &end, start_node, TRUE(!(0)), FALSE(0));
309
310 /* easy case first */
311 if (start_node == NULL((void*)0) || end_node == NULL((void*)0) || end_node == start_node->prev)
312 return;
313
314 /* deal with the start point */
315 start_is_outside = end_is_outside = FALSE(0);
316
317 sr = start_node->data;
318 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start);
319 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end);
320
321 if (gtk_text_iter_in_range (&start, &sr_start_iter, &sr_end_iter) &&
322 !gtk_text_iter_equal (&start, &sr_start_iter)) {
323 /* the starting point is inside the first subregion */
324 if (gtk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter) &&
325 !gtk_text_iter_equal (&end, &sr_end_iter)) {
326 /* the ending point is also inside the first
327 subregion: we need to split */
328 Subregion *new_sr = g_new0 (Subregion, 1)(Subregion *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (Subregion); gpointer __p; if (__s == 1) __p = g_malloc0
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s); __p
; }))
;
329 new_sr->end = sr->end;
330 new_sr->start = gtk_text_buffer_create_mark (region->buffer,
331 NULL((void*)0), &end, TRUE(!(0)));
332 start_node = g_list_insert_before (start_node, start_node->next, new_sr);
Value stored to 'start_node' is never read
333
334 sr->end = gtk_text_buffer_create_mark (region->buffer,
335 NULL((void*)0), &start, FALSE(0));
336
337 /* no further processing needed */
338 DEBUG (g_message ("subregion splitted"));
339
340 return;
341 } else {
342 /* the ending point is outside, so just move
343 the end of the subregion to the starting point */
344 gtk_text_buffer_move_mark (region->buffer, sr->end, &start);
345 }
346 } else {
347 /* the starting point is outside (and so to the left)
348 of the first subregion */
349 DEBUG (g_message ("start is outside"));
350
351 start_is_outside = TRUE(!(0));
352 }
353
354 /* deal with the end point */
355 if (start_node != end_node) {
356 sr = end_node->data;
357 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start);
358 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end);
359 }
360
361 if (gtk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter) &&
362 !gtk_text_iter_equal (&end, &sr_end_iter)) {
363 /* ending point is inside, move the start mark */
364 gtk_text_buffer_move_mark (region->buffer, sr->start, &end);
365 } else {
366 end_is_outside = TRUE(!(0));
367 DEBUG (g_message ("end is outside"));
368
369 }
370
371 /* finally remove any intermediate subregions */
372 done = FALSE(0);
373 node = start_node;
374
375 while (!done) {
376 if (node == end_node)
377 /* we are done, exit in the next iteration */
378 done = TRUE(!(0));
379
380 if ((node == start_node && !start_is_outside) ||
381 (node == end_node && !end_is_outside)) {
382 /* skip starting or ending node */
383 node = node->next;
384 } else {
385 GList *l = node->next;
386 sr = node->data;
387 gtk_text_buffer_delete_mark (region->buffer, sr->start);
388 gtk_text_buffer_delete_mark (region->buffer, sr->end);
389 g_free (sr);
390 region->subregions = g_list_delete_link (region->subregions,
391 node);
392 node = l;
393 }
394 }
395
396 ++region->time_stamp;
397
398 DEBUG (pluma_text_region_debug_print (region));
399
400 /* now get rid of empty subregions */
401 pluma_text_region_clear_zero_length_subregions (region);
402
403 DEBUG (pluma_text_region_debug_print (region));
404}
405
406gint
407pluma_text_region_subregions (PlumaTextRegion *region)
408{
409 g_return_val_if_fail (region != NULL, 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_59
; if (region != ((void*)0)) _g_boolean_var_59 = 1; else _g_boolean_var_59
= 0; _g_boolean_var_59; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return (0); } } while (0)
;
410
411 return g_list_length (region->subregions);
412}
413
414gboolean
415pluma_text_region_nth_subregion (PlumaTextRegion *region,
416 guint subregion,
417 GtkTextIter *start,
418 GtkTextIter *end)
419{
420 Subregion *sr;
421
422 g_return_val_if_fail (region != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_60
; if (region != ((void*)0)) _g_boolean_var_60 = 1; else _g_boolean_var_60
= 0; _g_boolean_var_60; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return ((0)); } } while (0)
;
423
424 sr = g_list_nth_data (region->subregions, subregion);
425 if (sr == NULL((void*)0))
426 return FALSE(0);
427
428 if (start)
429 gtk_text_buffer_get_iter_at_mark (region->buffer, start, sr->start);
430 if (end)
431 gtk_text_buffer_get_iter_at_mark (region->buffer, end, sr->end);
432
433 return TRUE(!(0));
434}
435
436PlumaTextRegion *
437pluma_text_region_intersect (PlumaTextRegion *region,
438 const GtkTextIter *_start,
439 const GtkTextIter *_end)
440{
441 GList *start_node, *end_node, *node;
442 GtkTextIter sr_start_iter, sr_end_iter;
443 Subregion *sr, *new_sr;
444 gboolean done;
445 PlumaTextRegion *new_region;
446 GtkTextIter start, end;
447
448 g_return_val_if_fail (region != NULL && _start != NULL && _end != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_61
; if (region != ((void*)0) && _start != ((void*)0) &&
_end != ((void*)0)) _g_boolean_var_61 = 1; else _g_boolean_var_61
= 0; _g_boolean_var_61; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL && _start != NULL && _end != NULL"
); return (((void*)0)); } } while (0)
;
449
450 start = *_start;
451 end = *_end;
452
453 gtk_text_iter_order (&start, &end);
454
455 /* find bounding subregions */
456 start_node = find_nearest_subregion (region, &start, NULL((void*)0), FALSE(0), FALSE(0));
457 end_node = find_nearest_subregion (region, &end, start_node, TRUE(!(0)), FALSE(0));
458
459 /* easy case first */
460 if (start_node == NULL((void*)0) || end_node == NULL((void*)0) || end_node == start_node->prev)
461 return NULL((void*)0);
462
463 new_region = pluma_text_region_new (region->buffer);
464 done = FALSE(0);
465
466 sr = start_node->data;
467 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start);
468 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end);
469
470 /* starting node */
471 if (gtk_text_iter_in_range (&start, &sr_start_iter, &sr_end_iter)) {
472 new_sr = g_new0 (Subregion, 1)(Subregion *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (Subregion); gpointer __p; if (__s == 1) __p = g_malloc0
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s); __p
; }))
;
473 new_region->subregions = g_list_prepend (new_region->subregions, new_sr);
474
475 new_sr->start = gtk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
476 &start, TRUE(!(0)));
477 if (start_node == end_node) {
478 /* things will finish shortly */
479 done = TRUE(!(0));
480 if (gtk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter))
481 new_sr->end = gtk_text_buffer_create_mark (new_region->buffer,
482 NULL((void*)0), &end, FALSE(0));
483 else
484 new_sr->end = gtk_text_buffer_create_mark (new_region->buffer,
485 NULL((void*)0), &sr_end_iter,
486 FALSE(0));
487 } else {
488 new_sr->end = gtk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
489 &sr_end_iter, FALSE(0));
490 }
491 node = start_node->next;
492 } else {
493 /* start should be the same as the subregion, so copy it in the loop */
494 node = start_node;
495 }
496
497 if (!done) {
498 while (node != end_node) {
499 /* copy intermediate subregions verbatim */
500 sr = node->data;
501 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter,
502 sr->start);
503 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end);
504
505 new_sr = g_new0 (Subregion, 1)(Subregion *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (Subregion); gpointer __p; if (__s == 1) __p = g_malloc0
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s); __p
; }))
;
506 new_region->subregions = g_list_prepend (new_region->subregions, new_sr);
507 new_sr->start = gtk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
508 &sr_start_iter, TRUE(!(0)));
509 new_sr->end = gtk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
510 &sr_end_iter, FALSE(0));
511 /* next node */
512 node = node->next;
513 }
514
515 /* ending node */
516 sr = node->data;
517 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start);
518 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end);
519
520 new_sr = g_new0 (Subregion, 1)(Subregion *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (Subregion); gpointer __p; if (__s == 1) __p = g_malloc0
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s); __p
; }))
;
521 new_region->subregions = g_list_prepend (new_region->subregions, new_sr);
522
523 new_sr->start = gtk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
524 &sr_start_iter, TRUE(!(0)));
525
526 if (gtk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter))
527 new_sr->end = gtk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
528 &end, FALSE(0));
529 else
530 new_sr->end = gtk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
531 &sr_end_iter, FALSE(0));
532 }
533
534 new_region->subregions = g_list_reverse (new_region->subregions);
535 return new_region;
536}
537
538static gboolean
539check_iterator (PlumaTextRegionIteratorReal *real)
540{
541 if ((real->region == NULL((void*)0)) ||
542 (real->region_time_stamp != real->region->time_stamp))
543 {
544 g_warning("Invalid iterator: either the iterator "
545 "is uninitialized, or the region "
546 "has been modified since the iterator "
547 "was created.");
548
549 return FALSE(0);
550 }
551
552 return TRUE(!(0));
553}
554
555void
556pluma_text_region_get_iterator (PlumaTextRegion *region,
557 PlumaTextRegionIterator *iter,
558 guint start)
559{
560 PlumaTextRegionIteratorReal *real;
561
562 g_return_if_fail (region != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_62
; if (region != ((void*)0)) _g_boolean_var_62 = 1; else _g_boolean_var_62
= 0; _g_boolean_var_62; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return; } } while (0)
;
563 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_63
; if (iter != ((void*)0)) _g_boolean_var_63 = 1; else _g_boolean_var_63
= 0; _g_boolean_var_63; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
564
565 real = (PlumaTextRegionIteratorReal *)iter;
566
567 /* region->subregions may be NULL, -> end iter */
568
569 real->region = region;
570 real->subregions = g_list_nth (region->subregions, start);
571 real->region_time_stamp = region->time_stamp;
572}
573
574gboolean
575pluma_text_region_iterator_is_end (PlumaTextRegionIterator *iter)
576{
577 PlumaTextRegionIteratorReal *real;
578
579 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_64
; if (iter != ((void*)0)) _g_boolean_var_64 = 1; else _g_boolean_var_64
= 0; _g_boolean_var_64; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
580
581 real = (PlumaTextRegionIteratorReal *)iter;
582 g_return_val_if_fail (check_iterator (real), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_65
; if (check_iterator (real)) _g_boolean_var_65 = 1; else _g_boolean_var_65
= 0; _g_boolean_var_65; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "check_iterator (real)"
); return ((0)); } } while (0)
;
583
584 return (real->subregions == NULL((void*)0));
585}
586
587gboolean
588pluma_text_region_iterator_next (PlumaTextRegionIterator *iter)
589{
590 PlumaTextRegionIteratorReal *real;
591
592 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_66
; if (iter != ((void*)0)) _g_boolean_var_66 = 1; else _g_boolean_var_66
= 0; _g_boolean_var_66; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
593
594 real = (PlumaTextRegionIteratorReal *)iter;
595 g_return_val_if_fail (check_iterator (real), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_67
; if (check_iterator (real)) _g_boolean_var_67 = 1; else _g_boolean_var_67
= 0; _g_boolean_var_67; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "check_iterator (real)"
); return ((0)); } } while (0)
;
596
597 if (real->subregions != NULL((void*)0)) {
598 real->subregions = g_list_next (real->subregions)((real->subregions) ? (((GList *)(real->subregions))->
next) : ((void*)0))
;
599 return TRUE(!(0));
600 }
601 else
602 return FALSE(0);
603}
604
605void
606pluma_text_region_iterator_get_subregion (PlumaTextRegionIterator *iter,
607 GtkTextIter *start,
608 GtkTextIter *end)
609{
610 PlumaTextRegionIteratorReal *real;
611 Subregion *sr;
612
613 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_68
; if (iter != ((void*)0)) _g_boolean_var_68 = 1; else _g_boolean_var_68
= 0; _g_boolean_var_68; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
614
615 real = (PlumaTextRegionIteratorReal *)iter;
616 g_return_if_fail (check_iterator (real))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_69
; if (check_iterator (real)) _g_boolean_var_69 = 1; else _g_boolean_var_69
= 0; _g_boolean_var_69; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "check_iterator (real)"
); return; } } while (0)
;
617 g_return_if_fail (real->subregions != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_70
; if (real->subregions != ((void*)0)) _g_boolean_var_70 = 1
; else _g_boolean_var_70 = 0; _g_boolean_var_70; }), 1))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "real->subregions != NULL"); return; } } while
(0)
;
618
619 sr = (Subregion*)real->subregions->data;
620 g_return_if_fail (sr != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_71
; if (sr != ((void*)0)) _g_boolean_var_71 = 1; else _g_boolean_var_71
= 0; _g_boolean_var_71; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "sr != NULL"); return
; } } while (0)
;
621
622 if (start)
623 gtk_text_buffer_get_iter_at_mark (real->region->buffer, start, sr->start);
624 if (end)
625 gtk_text_buffer_get_iter_at_mark (real->region->buffer, end, sr->end);
626}
627
628void
629pluma_text_region_debug_print (PlumaTextRegion *region)
630{
631 GList *l;
632
633 g_return_if_fail (region != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_72
; if (region != ((void*)0)) _g_boolean_var_72 = 1; else _g_boolean_var_72
= 0; _g_boolean_var_72; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return; } } while (0)
;
634
635 g_print ("Subregions: ");
636 l = region->subregions;
637 while (l) {
638 Subregion *sr = l->data;
639 GtkTextIter iter1, iter2;
640 gtk_text_buffer_get_iter_at_mark (region->buffer, &iter1, sr->start);
641 gtk_text_buffer_get_iter_at_mark (region->buffer, &iter2, sr->end);
642 g_print ("%d-%d ", gtk_text_iter_get_offset (&iter1),
643 gtk_text_iter_get_offset (&iter2));
644 l = l->next;
645 }
646 g_print ("\n");
647}
diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-5f782a.html b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-5f782a.html new file mode 100644 index 00000000..3367d764 --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-5f782a.html @@ -0,0 +1,1544 @@ + + + +pluma-spell-checker-dialog.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:plugins/spell/pluma-spell-checker-dialog.c
Warning:line 411, column 25
Use of memory after it is freed
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pluma-spell-checker-dialog.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/plugins/spell -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I ../.. -I ../.. -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/gtksourceview-4 -I /usr/include/libpeas-1.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/enchant-2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/dconf -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/plugins/spell -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-10-22-114445-13211-1 -x c pluma-spell-checker-dialog.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*
3 * pluma-spell-checker-dialog.c
4 * This file is part of pluma
5 *
6 * Copyright (C) 2002 Paolo Maggi
7 * Copyright (C) 2012-2021 MATE Developers
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 */
24
25/*
26 * Modified by the pluma Team, 2002. See the AUTHORS file for a
27 * list of people on the pluma Team.
28 * See the ChangeLog files for a list of changes.
29 */
30
31#ifdef HAVE_CONFIG_H1
32#include <config.h>
33#endif
34
35#include <string.h>
36#include <glib/gi18n.h>
37#include <gtk/gtk.h>
38#include <pluma/pluma-utils.h>
39#include "pluma-spell-checker-dialog.h"
40
41struct _PlumaSpellCheckerDialog
42{
43 GtkWindow parent_instance;
44
45 PlumaSpellChecker *spell_checker;
46
47 gchar *misspelled_word;
48
49 GtkWidget *misspelled_word_label;
50 GtkWidget *word_entry;
51 GtkWidget *check_word_button;
52 GtkWidget *ignore_button;
53 GtkWidget *ignore_all_button;
54 GtkWidget *change_button;
55 GtkWidget *change_all_button;
56 GtkWidget *add_word_button;
57 GtkWidget *close_button;
58 GtkWidget *suggestions_list;
59 GtkWidget *language_label;
60
61 GtkTreeModel *suggestions_list_model;
62};
63
64enum
65{
66 IGNORE,
67 IGNORE_ALL,
68 CHANGE,
69 CHANGE_ALL,
70 ADD_WORD_TO_PERSONAL,
71 LAST_SIGNAL
72};
73
74enum
75{
76 COLUMN_SUGGESTIONS,
77 NUM_COLUMNS
78};
79
80static void update_suggestions_list_model (PlumaSpellCheckerDialog *dlg,
81 GSList *suggestions);
82
83static void word_entry_changed_handler (GtkEditable *editable,
84 PlumaSpellCheckerDialog *dlg);
85static void close_button_clicked_handler (GtkButton *button,
86 PlumaSpellCheckerDialog *dlg);
87static void suggestions_list_selection_changed_handler (GtkTreeSelection *selection,
88 PlumaSpellCheckerDialog *dlg);
89static void check_word_button_clicked_handler (GtkButton *button,
90 PlumaSpellCheckerDialog *dlg);
91static void add_word_button_clicked_handler (GtkButton *button,
92 PlumaSpellCheckerDialog *dlg);
93static void ignore_button_clicked_handler (GtkButton *button,
94 PlumaSpellCheckerDialog *dlg);
95static void ignore_all_button_clicked_handler (GtkButton *button,
96 PlumaSpellCheckerDialog *dlg);
97static void change_button_clicked_handler (GtkButton *button,
98 PlumaSpellCheckerDialog *dlg);
99static void change_all_button_clicked_handler (GtkButton *button,
100 PlumaSpellCheckerDialog *dlg);
101static void suggestions_list_row_activated_handler (GtkTreeView *view,
102 GtkTreePath *path,
103 GtkTreeViewColumn *column,
104 PlumaSpellCheckerDialog *dlg);
105
106
107static guint signals [LAST_SIGNAL] = { 0 };
108
109G_DEFINE_TYPE(PlumaSpellCheckerDialog, pluma_spell_checker_dialog, GTK_TYPE_WINDOW)static void pluma_spell_checker_dialog_init (PlumaSpellCheckerDialog
*self); static void pluma_spell_checker_dialog_class_init (PlumaSpellCheckerDialogClass
*klass); static GType pluma_spell_checker_dialog_get_type_once
(void); static gpointer pluma_spell_checker_dialog_parent_class
= ((void*)0); static gint PlumaSpellCheckerDialog_private_offset
; static void pluma_spell_checker_dialog_class_intern_init (gpointer
klass) { pluma_spell_checker_dialog_parent_class = g_type_class_peek_parent
(klass); if (PlumaSpellCheckerDialog_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaSpellCheckerDialog_private_offset); pluma_spell_checker_dialog_class_init
((PlumaSpellCheckerDialogClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_spell_checker_dialog_get_instance_private
(PlumaSpellCheckerDialog *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaSpellCheckerDialog_private_offset))
)); } GType pluma_spell_checker_dialog_get_type (void) { static
gsize static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert
(sizeof *(&static_g_define_type_id) == sizeof (gpointer)
, "Expression evaluates to false"); (void) (0 ? (gpointer) *(
&static_g_define_type_id) : ((void*)0)); (!(__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id
)); }))) { GType g_define_type_id = pluma_spell_checker_dialog_get_type_once
(); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&static_g_define_type_id) = (g_define_type_id)
) : (void) 0; g_once_init_leave ((&static_g_define_type_id
), (gsize) (g_define_type_id)); })); } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType pluma_spell_checker_dialog_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((gtk_window_get_type ()), g_intern_static_string ("PlumaSpellCheckerDialog"
), sizeof (PlumaSpellCheckerDialogClass), (GClassInitFunc)(void
(*)(void)) pluma_spell_checker_dialog_class_intern_init, sizeof
(PlumaSpellCheckerDialog), (GInstanceInitFunc)(void (*)(void
)) pluma_spell_checker_dialog_init, (GTypeFlags) 0); { {{};} }
return g_define_type_id; }
110
111static void
112pluma_spell_checker_dialog_dispose (GObject *object)
113{
114 PlumaSpellCheckerDialog *dlg = PLUMA_SPELL_CHECKER_DIALOG (object)((((PlumaSpellCheckerDialog*) (void *) ((object)))));
115
116 if (dlg->spell_checker != NULL((void*)0))
117 {
118 g_object_unref (dlg->spell_checker);
119 dlg->spell_checker = NULL((void*)0);
120 }
121
122 if (dlg->misspelled_word != NULL((void*)0))
123 {
124 g_free (dlg->misspelled_word);
125 dlg->misspelled_word = NULL((void*)0);
126 }
127
128 G_OBJECT_CLASS (pluma_spell_checker_dialog_parent_class)((((GObjectClass*) (void *) ((pluma_spell_checker_dialog_parent_class
)))))
->dispose (object);
129}
130
131static void
132pluma_spell_checker_dialog_class_init (PlumaSpellCheckerDialogClass * klass)
133{
134 GObjectClass *object_class;
135
136 object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) ((klass)))));
137
138 object_class->dispose = pluma_spell_checker_dialog_dispose;
139
140 signals[IGNORE] =
141 g_signal_new ("ignore",
142 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
143 G_SIGNAL_RUN_LAST,
144 G_STRUCT_OFFSET (PlumaSpellCheckerDialogClass, ignore)((glong) __builtin_offsetof(PlumaSpellCheckerDialogClass, ignore
))
,
145 NULL((void*)0), NULL((void*)0), NULL((void*)0),
146 G_TYPE_NONE((GType) ((1) << (2))),
147 1,
148 G_TYPE_STRING((GType) ((16) << (2))));
149
150 signals[IGNORE_ALL] =
151 g_signal_new ("ignore_all",
152 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
153 G_SIGNAL_RUN_LAST,
154 G_STRUCT_OFFSET (PlumaSpellCheckerDialogClass, ignore_all)((glong) __builtin_offsetof(PlumaSpellCheckerDialogClass, ignore_all
))
,
155 NULL((void*)0), NULL((void*)0), NULL((void*)0),
156 G_TYPE_NONE((GType) ((1) << (2))),
157 1,
158 G_TYPE_STRING((GType) ((16) << (2))));
159
160 signals[CHANGE] =
161 g_signal_new ("change",
162 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
163 G_SIGNAL_RUN_LAST,
164 G_STRUCT_OFFSET (PlumaSpellCheckerDialogClass, change)((glong) __builtin_offsetof(PlumaSpellCheckerDialogClass, change
))
,
165 NULL((void*)0), NULL((void*)0), NULL((void*)0),
166 G_TYPE_NONE((GType) ((1) << (2))),
167 2,
168 G_TYPE_STRING((GType) ((16) << (2))),
169 G_TYPE_STRING((GType) ((16) << (2))));
170
171 signals[CHANGE_ALL] =
172 g_signal_new ("change_all",
173 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
174 G_SIGNAL_RUN_LAST,
175 G_STRUCT_OFFSET (PlumaSpellCheckerDialogClass, change_all)((glong) __builtin_offsetof(PlumaSpellCheckerDialogClass, change_all
))
,
176 NULL((void*)0), NULL((void*)0), NULL((void*)0),
177 G_TYPE_NONE((GType) ((1) << (2))),
178 2,
179 G_TYPE_STRING((GType) ((16) << (2))),
180 G_TYPE_STRING((GType) ((16) << (2))));
181
182 signals[ADD_WORD_TO_PERSONAL] =
183 g_signal_new ("add_word_to_personal",
184 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
185 G_SIGNAL_RUN_LAST,
186 G_STRUCT_OFFSET (PlumaSpellCheckerDialogClass, add_word_to_personal)((glong) __builtin_offsetof(PlumaSpellCheckerDialogClass, add_word_to_personal
))
,
187 NULL((void*)0), NULL((void*)0), NULL((void*)0),
188 G_TYPE_NONE((GType) ((1) << (2))),
189 1,
190 G_TYPE_STRING((GType) ((16) << (2))));
191}
192
193static void
194create_dialog (PlumaSpellCheckerDialog *dlg,
195 const gchar *data_dir)
196{
197 GtkWidget *error_widget;
198 GtkWidget *content;
199 GtkTreeViewColumn *column;
200 GtkCellRenderer *cell;
201 GtkTreeSelection *selection;
202 gchar *root_objects[] = {
203 "content",
204 "check_word_image",
205 "add_word_image",
206 "ignore_image",
207 "change_image",
208 "ignore_all_image",
209 "change_all_image",
210 NULL((void*)0)
211 };
212 gboolean ret;
213 gchar *ui_file;
214
215 g_return_if_fail (dlg != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_43
; if (dlg != ((void*)0)) _g_boolean_var_43 = 1; else _g_boolean_var_43
= 0; _g_boolean_var_43; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "dlg != NULL"); return
; } } while (0)
;
216
217 dlg->spell_checker = NULL((void*)0);
218 dlg->misspelled_word = NULL((void*)0);
219
220 ui_file = g_build_filename (data_dir, "spell-checker.ui", NULL((void*)0));
221 ret = pluma_utils_get_ui_objects (ui_file,
222 root_objects,
223 &error_widget,
224
225 "content", &content,
226 "misspelled_word_label", &dlg->misspelled_word_label,
227 "word_entry", &dlg->word_entry,
228 "check_word_button", &dlg->check_word_button,
229 "ignore_button", &dlg->ignore_button,
230 "ignore_all_button", &dlg->ignore_all_button,
231 "change_button", &dlg->change_button,
232 "change_all_button", &dlg->change_all_button,
233 "add_word_button", &dlg->add_word_button,
234 "close_button", &dlg->close_button,
235 "suggestions_list", &dlg->suggestions_list,
236 "language_label", &dlg->language_label,
237 NULL((void*)0));
238 g_free (ui_file);
239
240 if (!ret)
241 {
242 gtk_widget_show (error_widget);
243
244 gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg)))((((GtkBox*) (void *) ((gtk_dialog_get_content_area (((((GtkDialog
*) (void *) ((dlg)))))))))))
,
245 error_widget, TRUE(!(0)), TRUE(!(0)), 0);
246
247 return;
248 }
249
250 gtk_label_set_label (GTK_LABEL (dlg->misspelled_word_label)((((GtkLabel*) (void *) ((dlg->misspelled_word_label))))), "");
251 gtk_widget_set_sensitive (dlg->word_entry, FALSE(0));
252 gtk_widget_set_sensitive (dlg->check_word_button, FALSE(0));
253 gtk_widget_set_sensitive (dlg->ignore_button, FALSE(0));
254 gtk_widget_set_sensitive (dlg->ignore_all_button, FALSE(0));
255 gtk_widget_set_sensitive (dlg->change_button, FALSE(0));
256 gtk_widget_set_sensitive (dlg->change_all_button, FALSE(0));
257 gtk_widget_set_sensitive (dlg->add_word_button, FALSE(0));
258
259 gtk_label_set_label (GTK_LABEL (dlg->language_label)((((GtkLabel*) (void *) ((dlg->language_label))))), "");
260
261 gtk_container_add (GTK_CONTAINER (dlg)((((GtkContainer*) (void *) ((dlg))))), content);
262 g_object_unref (content);
263
264 gtk_window_set_resizable (GTK_WINDOW (dlg)((((GtkWindow*) (void *) ((dlg))))), FALSE(0));
265 gtk_window_set_title (GTK_WINDOW (dlg)((((GtkWindow*) (void *) ((dlg))))), _("Check Spelling")dcgettext (((void*)0), "Check Spelling", 5));
266
267 /* Suggestion list */
268 dlg->suggestions_list_model = GTK_TREE_MODEL (((((GtkTreeModel*) (void *) ((gtk_list_store_new (NUM_COLUMNS
, ((GType) ((16) << (2)))))))))
269 gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING))((((GtkTreeModel*) (void *) ((gtk_list_store_new (NUM_COLUMNS
, ((GType) ((16) << (2)))))))))
;
270
271 gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->suggestions_list)((((GtkTreeView*) (void *) ((dlg->suggestions_list))))),
272 dlg->suggestions_list_model);
273
274 /* Add the suggestions column */
275 cell = gtk_cell_renderer_text_new ();
276 column = gtk_tree_view_column_new_with_attributes (_("Suggestions")dcgettext (((void*)0), "Suggestions", 5), cell,
277 "text", COLUMN_SUGGESTIONS, NULL((void*)0));
278
279 gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->suggestions_list)((((GtkTreeView*) (void *) ((dlg->suggestions_list))))), column);
280
281 gtk_tree_view_set_search_column (GTK_TREE_VIEW (dlg->suggestions_list)((((GtkTreeView*) (void *) ((dlg->suggestions_list))))),
282 COLUMN_SUGGESTIONS);
283
284 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->suggestions_list)((((GtkTreeView*) (void *) ((dlg->suggestions_list))))));
285
286 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
287
288 /* Set default button */
289 gtk_widget_set_can_default (dlg->change_button, TRUE(!(0)));
290 gtk_widget_grab_default (dlg->change_button);
291
292 gtk_entry_set_activates_default (GTK_ENTRY (dlg->word_entry)((((GtkEntry*) (void *) ((dlg->word_entry))))), TRUE(!(0)));
293
294 gtk_button_set_image (GTK_BUTTON (dlg->close_button)((((GtkButton*) (void *) ((dlg->close_button))))),
295 gtk_image_new_from_icon_name ("window-close", GTK_ICON_SIZE_BUTTON));
296
297 /* Connect signals */
298 g_signal_connect (dlg->word_entry, "changed",g_signal_connect_data ((dlg->word_entry), ("changed"), (((
GCallback) (word_entry_changed_handler))), (dlg), ((void*)0),
(GConnectFlags) 0)
299 G_CALLBACK (word_entry_changed_handler), dlg)g_signal_connect_data ((dlg->word_entry), ("changed"), (((
GCallback) (word_entry_changed_handler))), (dlg), ((void*)0),
(GConnectFlags) 0)
;
300 g_signal_connect (dlg->close_button, "clicked",g_signal_connect_data ((dlg->close_button), ("clicked"), (
((GCallback) (close_button_clicked_handler))), (dlg), ((void*
)0), (GConnectFlags) 0)
301 G_CALLBACK (close_button_clicked_handler), dlg)g_signal_connect_data ((dlg->close_button), ("clicked"), (
((GCallback) (close_button_clicked_handler))), (dlg), ((void*
)0), (GConnectFlags) 0)
;
302 g_signal_connect (selection, "changed",g_signal_connect_data ((selection), ("changed"), (((GCallback
) (suggestions_list_selection_changed_handler))), (dlg), ((void
*)0), (GConnectFlags) 0)
303 G_CALLBACK (suggestions_list_selection_changed_handler),g_signal_connect_data ((selection), ("changed"), (((GCallback
) (suggestions_list_selection_changed_handler))), (dlg), ((void
*)0), (GConnectFlags) 0)
304 dlg)g_signal_connect_data ((selection), ("changed"), (((GCallback
) (suggestions_list_selection_changed_handler))), (dlg), ((void
*)0), (GConnectFlags) 0)
;
305 g_signal_connect (dlg->check_word_button, "clicked",g_signal_connect_data ((dlg->check_word_button), ("clicked"
), (((GCallback) (check_word_button_clicked_handler))), (dlg)
, ((void*)0), (GConnectFlags) 0)
306 G_CALLBACK (check_word_button_clicked_handler), dlg)g_signal_connect_data ((dlg->check_word_button), ("clicked"
), (((GCallback) (check_word_button_clicked_handler))), (dlg)
, ((void*)0), (GConnectFlags) 0)
;
307 g_signal_connect (dlg->add_word_button, "clicked",g_signal_connect_data ((dlg->add_word_button), ("clicked")
, (((GCallback) (add_word_button_clicked_handler))), (dlg), (
(void*)0), (GConnectFlags) 0)
308 G_CALLBACK (add_word_button_clicked_handler), dlg)g_signal_connect_data ((dlg->add_word_button), ("clicked")
, (((GCallback) (add_word_button_clicked_handler))), (dlg), (
(void*)0), (GConnectFlags) 0)
;
309 g_signal_connect (dlg->ignore_button, "clicked",g_signal_connect_data ((dlg->ignore_button), ("clicked"), (
((GCallback) (ignore_button_clicked_handler))), (dlg), ((void
*)0), (GConnectFlags) 0)
310 G_CALLBACK (ignore_button_clicked_handler), dlg)g_signal_connect_data ((dlg->ignore_button), ("clicked"), (
((GCallback) (ignore_button_clicked_handler))), (dlg), ((void
*)0), (GConnectFlags) 0)
;
311 g_signal_connect (dlg->ignore_all_button, "clicked",g_signal_connect_data ((dlg->ignore_all_button), ("clicked"
), (((GCallback) (ignore_all_button_clicked_handler))), (dlg)
, ((void*)0), (GConnectFlags) 0)
312 G_CALLBACK (ignore_all_button_clicked_handler), dlg)g_signal_connect_data ((dlg->ignore_all_button), ("clicked"
), (((GCallback) (ignore_all_button_clicked_handler))), (dlg)
, ((void*)0), (GConnectFlags) 0)
;
313 g_signal_connect (dlg->change_button, "clicked",g_signal_connect_data ((dlg->change_button), ("clicked"), (
((GCallback) (change_button_clicked_handler))), (dlg), ((void
*)0), (GConnectFlags) 0)
314 G_CALLBACK (change_button_clicked_handler), dlg)g_signal_connect_data ((dlg->change_button), ("clicked"), (
((GCallback) (change_button_clicked_handler))), (dlg), ((void
*)0), (GConnectFlags) 0)
;
315 g_signal_connect (dlg->change_all_button, "clicked",g_signal_connect_data ((dlg->change_all_button), ("clicked"
), (((GCallback) (change_all_button_clicked_handler))), (dlg)
, ((void*)0), (GConnectFlags) 0)
316 G_CALLBACK (change_all_button_clicked_handler), dlg)g_signal_connect_data ((dlg->change_all_button), ("clicked"
), (((GCallback) (change_all_button_clicked_handler))), (dlg)
, ((void*)0), (GConnectFlags) 0)
;
317 g_signal_connect (dlg->suggestions_list, "row-activated",g_signal_connect_data ((dlg->suggestions_list), ("row-activated"
), (((GCallback) (suggestions_list_row_activated_handler))), (
dlg), ((void*)0), (GConnectFlags) 0)
318 G_CALLBACK (suggestions_list_row_activated_handler), dlg)g_signal_connect_data ((dlg->suggestions_list), ("row-activated"
), (((GCallback) (suggestions_list_row_activated_handler))), (
dlg), ((void*)0), (GConnectFlags) 0)
;
319}
320
321static void
322pluma_spell_checker_dialog_init (PlumaSpellCheckerDialog *dlg)
323{
324}
325
326GtkWidget *
327pluma_spell_checker_dialog_new (const gchar *data_dir)
328{
329 PlumaSpellCheckerDialog *dlg;
330
331 dlg = PLUMA_SPELL_CHECKER_DIALOG (((((PlumaSpellCheckerDialog*) (void *) ((g_object_new ((pluma_spell_checker_dialog_get_type
()), ((void*)0)))))))
332 g_object_new (PLUMA_TYPE_SPELL_CHECKER_DIALOG, NULL))((((PlumaSpellCheckerDialog*) (void *) ((g_object_new ((pluma_spell_checker_dialog_get_type
()), ((void*)0)))))))
;
333
334 g_return_val_if_fail (dlg != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_44
; if (dlg != ((void*)0)) _g_boolean_var_44 = 1; else _g_boolean_var_44
= 0; _g_boolean_var_44; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "dlg != NULL"); return
(((void*)0)); } } while (0)
;
335
336 create_dialog (dlg, data_dir);
337
338 return GTK_WIDGET (dlg)((((GtkWidget*) (void *) ((dlg)))));
339}
340
341GtkWidget *
342pluma_spell_checker_dialog_new_from_spell_checker (PlumaSpellChecker *spell,
343 const gchar *data_dir)
344{
345 PlumaSpellCheckerDialog *dlg;
346
347 g_return_val_if_fail (spell != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_45
; if (spell != ((void*)0)) _g_boolean_var_45 = 1; else _g_boolean_var_45
= 0; _g_boolean_var_45; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "spell != NULL");
return (((void*)0)); } } while (0)
;
1
Assuming 'spell' is not equal to null
2
Taking true branch
3
Taking true branch
4
Loop condition is false. Exiting loop
348
349 dlg = PLUMA_SPELL_CHECKER_DIALOG (((((PlumaSpellCheckerDialog*) (void *) ((g_object_new ((pluma_spell_checker_dialog_get_type
()), ((void*)0)))))))
350 g_object_new (PLUMA_TYPE_SPELL_CHECKER_DIALOG, NULL))((((PlumaSpellCheckerDialog*) (void *) ((g_object_new ((pluma_spell_checker_dialog_get_type
()), ((void*)0)))))))
;
351
352 g_return_val_if_fail (dlg != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_46
; if (dlg != ((void*)0)) _g_boolean_var_46 = 1; else _g_boolean_var_46
= 0; _g_boolean_var_46; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "dlg != NULL"); return
(((void*)0)); } } while (0)
;
5
Assuming 'dlg' is not equal to null
6
Taking true branch
7
Taking true branch
8
Loop condition is false. Exiting loop
353
354 create_dialog (dlg, data_dir);
355
356 pluma_spell_checker_dialog_set_spell_checker (dlg, spell);
9
Calling 'pluma_spell_checker_dialog_set_spell_checker'
357
358 return GTK_WIDGET (dlg)((((GtkWidget*) (void *) ((dlg)))));
359}
360
361void
362pluma_spell_checker_dialog_set_spell_checker (PlumaSpellCheckerDialog *dlg, PlumaSpellChecker *spell)
363{
364 const PlumaSpellCheckerLanguage* language;
365 const gchar *lang;
366 gchar *tmp;
367
368 g_return_if_fail (PLUMA_IS_SPELL_CHECKER_DIALOG (dlg))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_47
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dlg)); GType __t = ((pluma_spell_checker_dialog_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_47 = 1; else _g_boolean_var_47 = 0
; _g_boolean_var_47; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_SPELL_CHECKER_DIALOG (dlg)"
); return; } } while (0)
;
10
Taking false branch
11
Assuming field 'g_class' is null
12
Assuming the condition is true
13
Taking true branch
14
Taking true branch
15
Loop condition is false. Exiting loop
369 g_return_if_fail (spell != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_48
; if (spell != ((void*)0)) _g_boolean_var_48 = 1; else _g_boolean_var_48
= 0; _g_boolean_var_48; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "spell != NULL");
return; } } while (0)
;
16
Taking true branch
17
Taking true branch
18
Loop condition is false. Exiting loop
370
371 if (dlg->spell_checker != NULL((void*)0))
19
Assuming field 'spell_checker' is equal to NULL
20
Taking false branch
372 g_object_unref (dlg->spell_checker);
373
374 dlg->spell_checker = spell;
375 g_object_ref (dlg->spell_checker)((__typeof__ (dlg->spell_checker)) (g_object_ref) (dlg->
spell_checker))
;
376
377 language = pluma_spell_checker_get_language (dlg->spell_checker);
378
379 lang = pluma_spell_checker_language_to_string (language);
380 tmp = g_strdup_printf("<b>%s</b>", lang);
381
382 gtk_label_set_label (GTK_LABEL (dlg->language_label)((((GtkLabel*) (void *) ((dlg->language_label))))), tmp);
383 g_free (tmp);
384
385 if (dlg->misspelled_word != NULL((void*)0))
21
Assuming field 'misspelled_word' is not equal to NULL
22
Taking true branch
386 pluma_spell_checker_dialog_set_misspelled_word (dlg, dlg->misspelled_word, -1);
23
Calling 'pluma_spell_checker_dialog_set_misspelled_word'
387 else
388 gtk_list_store_clear (GTK_LIST_STORE (dlg->suggestions_list_model)((((GtkListStore*) (void *) ((dlg->suggestions_list_model)
))))
);
389
390 /* TODO: reset all widgets */
391}
392
393void
394pluma_spell_checker_dialog_set_misspelled_word (PlumaSpellCheckerDialog *dlg,
395 const gchar *word,
396 gint len)
397{
398 gchar *tmp;
399 GSList *sug;
400
401 g_return_if_fail (PLUMA_IS_SPELL_CHECKER_DIALOG (dlg))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_49
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dlg)); GType __t = ((pluma_spell_checker_dialog_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_49 = 1; else _g_boolean_var_49 = 0
; _g_boolean_var_49; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_SPELL_CHECKER_DIALOG (dlg)"
); return; } } while (0)
;
24
Taking false branch
25
Assuming the condition is true
26
Taking true branch
27
Taking true branch
28
Loop condition is false. Exiting loop
402 g_return_if_fail (word != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_50
; if (word != ((void*)0)) _g_boolean_var_50 = 1; else _g_boolean_var_50
= 0; _g_boolean_var_50; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "word != NULL"); return
; } } while (0)
;
29
Taking true branch
30
Taking true branch
31
Loop condition is false. Exiting loop
403
404 g_return_if_fail (dlg->spell_checker != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_51
; if (dlg->spell_checker != ((void*)0)) _g_boolean_var_51 =
1; else _g_boolean_var_51 = 0; _g_boolean_var_51; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "dlg->spell_checker != NULL"); return; } }
while (0)
;
32
Taking true branch
33
Taking true branch
34
Loop condition is false. Exiting loop
405 g_return_if_fail (!pluma_spell_checker_check_word (dlg->spell_checker, word, -1))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_52
; if (!pluma_spell_checker_check_word (dlg->spell_checker,
word, -1)) _g_boolean_var_52 = 1; else _g_boolean_var_52 = 0
; _g_boolean_var_52; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "!pluma_spell_checker_check_word (dlg->spell_checker, word, -1)"
); return; } } while (0)
;
35
Assuming the condition is true
36
Taking true branch
37
Taking true branch
38
Loop condition is false. Exiting loop
406
407 /* build_suggestions_list */
408 if (dlg->misspelled_word
38.1
Field 'misspelled_word' is not equal to NULL
!= NULL((void*)0))
39
Taking true branch
409 g_free (dlg->misspelled_word);
40
Memory is released
410
411 dlg->misspelled_word = g_strdup (word)g_strdup_inline (word);
41
Use of memory after it is freed
412
413 tmp = g_strdup_printf("<b>%s</b>", word);
414 gtk_label_set_label (GTK_LABEL (dlg->misspelled_word_label)((((GtkLabel*) (void *) ((dlg->misspelled_word_label))))), tmp);
415 g_free (tmp);
416
417 sug = pluma_spell_checker_get_suggestions (dlg->spell_checker,
418 dlg->misspelled_word,
419 -1);
420
421 update_suggestions_list_model (dlg, sug);
422
423 /* free the suggestion list */
424 g_slist_free_full (sug, g_free);
425
426 gtk_widget_set_sensitive (dlg->ignore_button, TRUE(!(0)));
427 gtk_widget_set_sensitive (dlg->ignore_all_button, TRUE(!(0)));
428 gtk_widget_set_sensitive (dlg->add_word_button, TRUE(!(0)));
429}
430
431static void
432update_suggestions_list_model (PlumaSpellCheckerDialog *dlg, GSList *suggestions)
433{
434 GtkListStore *store;
435 GtkTreeIter iter;
436 GtkTreeSelection *sel;
437
438 g_return_if_fail (PLUMA_IS_SPELL_CHECKER_DIALOG (dlg))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_53
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dlg)); GType __t = ((pluma_spell_checker_dialog_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_53 = 1; else _g_boolean_var_53 = 0
; _g_boolean_var_53; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_SPELL_CHECKER_DIALOG (dlg)"
); return; } } while (0)
;
439 g_return_if_fail (GTK_IS_LIST_STORE (dlg->suggestions_list_model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_54
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dlg->suggestions_list_model)); GType __t = ((gtk_list_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_54 = 1; else _g_boolean_var_54 = 0
; _g_boolean_var_54; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "GTK_IS_LIST_STORE (dlg->suggestions_list_model)"
); return; } } while (0)
;
440
441 store = GTK_LIST_STORE (dlg->suggestions_list_model)((((GtkListStore*) (void *) ((dlg->suggestions_list_model)
))))
;
442 gtk_list_store_clear (store);
443
444 gtk_widget_set_sensitive (dlg->word_entry, TRUE(!(0)));
445
446 if (suggestions == NULL((void*)0))
447 {
448 gtk_list_store_append (store, &iter);
449 gtk_list_store_set (store, &iter,
450 /* Translators: Displayed in the "Check Spelling" dialog if there are no suggestions
451 * for the current misspelled word */
452 COLUMN_SUGGESTIONS, _("(no suggested words)")dcgettext (((void*)0), "(no suggested words)", 5),
453 -1);
454
455 gtk_entry_set_text (GTK_ENTRY (dlg->word_entry)((((GtkEntry*) (void *) ((dlg->word_entry))))), "");
456
457 gtk_widget_set_sensitive (dlg->suggestions_list, FALSE(0));
458
459 return;
460 }
461
462 gtk_widget_set_sensitive (dlg->suggestions_list, TRUE(!(0)));
463
464 gtk_entry_set_text (GTK_ENTRY (dlg->word_entry)((((GtkEntry*) (void *) ((dlg->word_entry))))), (gchar*)suggestions->data);
465
466 while (suggestions != NULL((void*)0))
467 {
468 gtk_list_store_append (store, &iter);
469 gtk_list_store_set (store, &iter,
470 COLUMN_SUGGESTIONS, (gchar*)suggestions->data,
471 -1);
472
473 suggestions = g_slist_next (suggestions)((suggestions) ? (((GSList *)(suggestions))->next) : ((void
*)0))
;
474 }
475
476 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->suggestions_list)((((GtkTreeView*) (void *) ((dlg->suggestions_list))))));
477 gtk_tree_model_get_iter_first (dlg->suggestions_list_model, &iter);
478 gtk_tree_selection_select_iter (sel, &iter);
479}
480
481static void
482word_entry_changed_handler (GtkEditable *editable, PlumaSpellCheckerDialog *dlg)
483{
484 const gchar *text;
485
486 g_return_if_fail (PLUMA_IS_SPELL_CHECKER_DIALOG (dlg))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_55
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dlg)); GType __t = ((pluma_spell_checker_dialog_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_55 = 1; else _g_boolean_var_55 = 0
; _g_boolean_var_55; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_SPELL_CHECKER_DIALOG (dlg)"
); return; } } while (0)
;
487
488 text = gtk_entry_get_text (GTK_ENTRY (dlg->word_entry)((((GtkEntry*) (void *) ((dlg->word_entry))))));
489
490 if (g_utf8_strlen (text, -1) > 0)
491 {
492 gtk_widget_set_sensitive (dlg->check_word_button, TRUE(!(0)));
493 gtk_widget_set_sensitive (dlg->change_button, TRUE(!(0)));
494 gtk_widget_set_sensitive (dlg->change_all_button, TRUE(!(0)));
495 }
496 else
497 {
498 gtk_widget_set_sensitive (dlg->check_word_button, FALSE(0));
499 gtk_widget_set_sensitive (dlg->change_button, FALSE(0));
500 gtk_widget_set_sensitive (dlg->change_all_button, FALSE(0));
501 }
502}
503
504static void
505close_button_clicked_handler (GtkButton *button, PlumaSpellCheckerDialog *dlg)
506{
507 g_return_if_fail (PLUMA_IS_SPELL_CHECKER_DIALOG (dlg))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_56
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dlg)); GType __t = ((pluma_spell_checker_dialog_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_56 = 1; else _g_boolean_var_56 = 0
; _g_boolean_var_56; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_SPELL_CHECKER_DIALOG (dlg)"
); return; } } while (0)
;
508
509 gtk_widget_destroy (GTK_WIDGET (dlg)((((GtkWidget*) (void *) ((dlg))))));
510}
511
512static void
513suggestions_list_selection_changed_handler (GtkTreeSelection *selection,
514 PlumaSpellCheckerDialog *dlg)
515{
516 GtkTreeIter iter;
517 GValue value = {0, };
518 const gchar *text;
519
520 g_return_if_fail (PLUMA_IS_SPELL_CHECKER_DIALOG (dlg))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_57
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dlg)); GType __t = ((pluma_spell_checker_dialog_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_57 = 1; else _g_boolean_var_57 = 0
; _g_boolean_var_57; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_SPELL_CHECKER_DIALOG (dlg)"
); return; } } while (0)
;
521
522 if (! gtk_tree_selection_get_selected (selection, NULL((void*)0), &iter))
523 return;
524
525 gtk_tree_model_get_value (dlg->suggestions_list_model, &iter,
526 COLUMN_SUGGESTIONS,
527 &value);
528
529 text = g_value_get_string (&value);
530
531 gtk_entry_set_text (GTK_ENTRY (dlg->word_entry)((((GtkEntry*) (void *) ((dlg->word_entry))))), text);
532
533 g_value_unset (&value);
534}
535
536static void
537check_word_button_clicked_handler (GtkButton *button, PlumaSpellCheckerDialog *dlg)
538{
539 const gchar *word;
540 gssize len;
541
542 g_return_if_fail (PLUMA_IS_SPELL_CHECKER_DIALOG (dlg))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_58
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dlg)); GType __t = ((pluma_spell_checker_dialog_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_58 = 1; else _g_boolean_var_58 = 0
; _g_boolean_var_58; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_SPELL_CHECKER_DIALOG (dlg)"
); return; } } while (0)
;
543
544 word = gtk_entry_get_text (GTK_ENTRY (dlg->word_entry)((((GtkEntry*) (void *) ((dlg->word_entry))))));
545 len = strlen (word);
546 g_return_if_fail (len > 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_59
; if (len > 0) _g_boolean_var_59 = 1; else _g_boolean_var_59
= 0; _g_boolean_var_59; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "len > 0"); return
; } } while (0)
;
547
548 if (pluma_spell_checker_check_word (dlg->spell_checker, word, len))
549 {
550 GtkListStore *store;
551 GtkTreeIter iter;
552
553 store = GTK_LIST_STORE (dlg->suggestions_list_model)((((GtkListStore*) (void *) ((dlg->suggestions_list_model)
))))
;
554 gtk_list_store_clear (store);
555
556 gtk_list_store_append (store, &iter);
557 gtk_list_store_set (store, &iter,
558 /* Translators: Displayed in the "Check Spelling" dialog if the current word isn't misspelled */
559 COLUMN_SUGGESTIONS, _("(correct spelling)")dcgettext (((void*)0), "(correct spelling)", 5),
560 -1);
561
562 gtk_widget_set_sensitive (dlg->suggestions_list, FALSE(0));
563 }
564 else
565 {
566 GSList *sug;
567
568 sug = pluma_spell_checker_get_suggestions (dlg->spell_checker,
569 word,
570 len);
571
572 update_suggestions_list_model (dlg, sug);
573
574 /* free the suggestion list */
575 g_slist_free_full (sug, g_free);
576 }
577}
578
579static void
580add_word_button_clicked_handler (GtkButton *button, PlumaSpellCheckerDialog *dlg)
581{
582 gchar *word;
583
584 g_return_if_fail (PLUMA_IS_SPELL_CHECKER_DIALOG (dlg))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_60
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dlg)); GType __t = ((pluma_spell_checker_dialog_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_60 = 1; else _g_boolean_var_60 = 0
; _g_boolean_var_60; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_SPELL_CHECKER_DIALOG (dlg)"
); return; } } while (0)
;
585 g_return_if_fail (dlg->misspelled_word != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_61
; if (dlg->misspelled_word != ((void*)0)) _g_boolean_var_61
= 1; else _g_boolean_var_61 = 0; _g_boolean_var_61; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "dlg->misspelled_word != NULL"); return; }
} while (0)
;
586
587 pluma_spell_checker_add_word_to_personal (dlg->spell_checker,
588 dlg->misspelled_word,
589 -1);
590
591 word = g_strdup (dlg->misspelled_word)g_strdup_inline (dlg->misspelled_word);
592
593 g_signal_emit (G_OBJECT (dlg)((((GObject*) (void *) ((dlg))))), signals [ADD_WORD_TO_PERSONAL], 0, word);
594
595 g_free (word);
596}
597
598static void
599ignore_button_clicked_handler (GtkButton *button, PlumaSpellCheckerDialog *dlg)
600{
601 gchar *word;
602
603 g_return_if_fail (PLUMA_IS_SPELL_CHECKER_DIALOG (dlg))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_62
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dlg)); GType __t = ((pluma_spell_checker_dialog_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_62 = 1; else _g_boolean_var_62 = 0
; _g_boolean_var_62; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_SPELL_CHECKER_DIALOG (dlg)"
); return; } } while (0)
;
604 g_return_if_fail (dlg->misspelled_word != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_63
; if (dlg->misspelled_word != ((void*)0)) _g_boolean_var_63
= 1; else _g_boolean_var_63 = 0; _g_boolean_var_63; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "dlg->misspelled_word != NULL"); return; }
} while (0)
;
605
606 word = g_strdup (dlg->misspelled_word)g_strdup_inline (dlg->misspelled_word);
607
608 g_signal_emit (G_OBJECT (dlg)((((GObject*) (void *) ((dlg))))), signals [IGNORE], 0, word);
609
610 g_free (word);
611}
612
613static void
614ignore_all_button_clicked_handler (GtkButton *button, PlumaSpellCheckerDialog *dlg)
615{
616 gchar *word;
617
618 g_return_if_fail (PLUMA_IS_SPELL_CHECKER_DIALOG (dlg))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_64
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dlg)); GType __t = ((pluma_spell_checker_dialog_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_64 = 1; else _g_boolean_var_64 = 0
; _g_boolean_var_64; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_SPELL_CHECKER_DIALOG (dlg)"
); return; } } while (0)
;
619 g_return_if_fail (dlg->misspelled_word != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_65
; if (dlg->misspelled_word != ((void*)0)) _g_boolean_var_65
= 1; else _g_boolean_var_65 = 0; _g_boolean_var_65; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "dlg->misspelled_word != NULL"); return; }
} while (0)
;
620
621 pluma_spell_checker_add_word_to_session (dlg->spell_checker,
622 dlg->misspelled_word,
623 -1);
624
625 word = g_strdup (dlg->misspelled_word)g_strdup_inline (dlg->misspelled_word);
626
627 g_signal_emit (G_OBJECT (dlg)((((GObject*) (void *) ((dlg))))), signals [IGNORE_ALL], 0, word);
628
629 g_free (word);
630}
631
632static void
633change_button_clicked_handler (GtkButton *button, PlumaSpellCheckerDialog *dlg)
634{
635 const gchar *entry_text;
636 gchar *change;
637 gchar *word;
638
639 g_return_if_fail (PLUMA_IS_SPELL_CHECKER_DIALOG (dlg))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_66
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dlg)); GType __t = ((pluma_spell_checker_dialog_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_66 = 1; else _g_boolean_var_66 = 0
; _g_boolean_var_66; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_SPELL_CHECKER_DIALOG (dlg)"
); return; } } while (0)
;
640 g_return_if_fail (dlg->misspelled_word != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_67
; if (dlg->misspelled_word != ((void*)0)) _g_boolean_var_67
= 1; else _g_boolean_var_67 = 0; _g_boolean_var_67; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "dlg->misspelled_word != NULL"); return; }
} while (0)
;
641
642 entry_text = gtk_entry_get_text (GTK_ENTRY (dlg->word_entry)((((GtkEntry*) (void *) ((dlg->word_entry))))));
643 g_return_if_fail (entry_text != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_68
; if (entry_text != ((void*)0)) _g_boolean_var_68 = 1; else _g_boolean_var_68
= 0; _g_boolean_var_68; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "entry_text != NULL"
); return; } } while (0)
;
644 g_return_if_fail (*entry_text != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_69
; if (*entry_text != '\0') _g_boolean_var_69 = 1; else _g_boolean_var_69
= 0; _g_boolean_var_69; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "*entry_text != '\\0'"
); return; } } while (0)
;
645 change = g_strdup (entry_text)g_strdup_inline (entry_text);
646
647 pluma_spell_checker_set_correction (dlg->spell_checker,
648 dlg->misspelled_word, -1,
649 change, -1);
650
651 word = g_strdup (dlg->misspelled_word)g_strdup_inline (dlg->misspelled_word);
652
653 g_signal_emit (G_OBJECT (dlg)((((GObject*) (void *) ((dlg))))), signals [CHANGE], 0, word, change);
654
655 g_free (word);
656 g_free (change);
657}
658
659/* double click on one of the suggestions is like clicking on "change" */
660static void
661suggestions_list_row_activated_handler (GtkTreeView *view,
662 GtkTreePath *path,
663 GtkTreeViewColumn *column,
664 PlumaSpellCheckerDialog *dlg)
665{
666 g_return_if_fail (PLUMA_IS_SPELL_CHECKER_DIALOG (dlg))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_70
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dlg)); GType __t = ((pluma_spell_checker_dialog_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_70 = 1; else _g_boolean_var_70 = 0
; _g_boolean_var_70; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_SPELL_CHECKER_DIALOG (dlg)"
); return; } } while (0)
;
667
668 change_button_clicked_handler (GTK_BUTTON (dlg->change_button)((((GtkButton*) (void *) ((dlg->change_button))))), dlg);
669}
670
671static void
672change_all_button_clicked_handler (GtkButton *button, PlumaSpellCheckerDialog *dlg)
673{
674 const gchar *entry_text;
675 gchar *change;
676 gchar *word;
677
678 g_return_if_fail (PLUMA_IS_SPELL_CHECKER_DIALOG (dlg))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_71
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dlg)); GType __t = ((pluma_spell_checker_dialog_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_71 = 1; else _g_boolean_var_71 = 0
; _g_boolean_var_71; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_SPELL_CHECKER_DIALOG (dlg)"
); return; } } while (0)
;
679 g_return_if_fail (dlg->misspelled_word != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_72
; if (dlg->misspelled_word != ((void*)0)) _g_boolean_var_72
= 1; else _g_boolean_var_72 = 0; _g_boolean_var_72; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "dlg->misspelled_word != NULL"); return; }
} while (0)
;
680
681 entry_text = gtk_entry_get_text (GTK_ENTRY (dlg->word_entry)((((GtkEntry*) (void *) ((dlg->word_entry))))));
682 g_return_if_fail (entry_text != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_73
; if (entry_text != ((void*)0)) _g_boolean_var_73 = 1; else _g_boolean_var_73
= 0; _g_boolean_var_73; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "entry_text != NULL"
); return; } } while (0)
;
683 g_return_if_fail (*entry_text != '\0')do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_74
; if (*entry_text != '\0') _g_boolean_var_74 = 1; else _g_boolean_var_74
= 0; _g_boolean_var_74; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "*entry_text != '\\0'"
); return; } } while (0)
;
684 change = g_strdup (entry_text)g_strdup_inline (entry_text);
685
686 pluma_spell_checker_set_correction (dlg->spell_checker,
687 dlg->misspelled_word, -1,
688 change, -1);
689
690 word = g_strdup (dlg->misspelled_word)g_strdup_inline (dlg->misspelled_word);
691
692 g_signal_emit (G_OBJECT (dlg)((((GObject*) (void *) ((dlg))))), signals [CHANGE_ALL], 0, word, change);
693
694 g_free (word);
695 g_free (change);
696}
697
698void
699pluma_spell_checker_dialog_set_completed (PlumaSpellCheckerDialog *dlg)
700{
701 gchar *tmp;
702
703 g_return_if_fail (PLUMA_IS_SPELL_CHECKER_DIALOG (dlg))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_75
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((dlg)); GType __t = ((pluma_spell_checker_dialog_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_75 = 1; else _g_boolean_var_75 = 0
; _g_boolean_var_75; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_SPELL_CHECKER_DIALOG (dlg)"
); return; } } while (0)
;
704
705 tmp = g_strdup_printf("<b>%s</b>", _("Completed spell checking")dcgettext (((void*)0), "Completed spell checking", 5));
706 gtk_label_set_label (GTK_LABEL (dlg->misspelled_word_label)((((GtkLabel*) (void *) ((dlg->misspelled_word_label))))),
707 tmp);
708 g_free (tmp);
709
710 gtk_list_store_clear (GTK_LIST_STORE (dlg->suggestions_list_model)((((GtkListStore*) (void *) ((dlg->suggestions_list_model)
))))
);
711 gtk_entry_set_text (GTK_ENTRY (dlg->word_entry)((((GtkEntry*) (void *) ((dlg->word_entry))))), "");
712
713 gtk_widget_set_sensitive (dlg->word_entry, FALSE(0));
714 gtk_widget_set_sensitive (dlg->check_word_button, FALSE(0));
715 gtk_widget_set_sensitive (dlg->ignore_button, FALSE(0));
716 gtk_widget_set_sensitive (dlg->ignore_all_button, FALSE(0));
717 gtk_widget_set_sensitive (dlg->change_button, FALSE(0));
718 gtk_widget_set_sensitive (dlg->change_all_button, FALSE(0));
719 gtk_widget_set_sensitive (dlg->add_word_button, FALSE(0));
720 gtk_widget_set_sensitive (dlg->suggestions_list, FALSE(0));
721}
722
diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-6c7faf.html b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-6c7faf.html new file mode 100644 index 00000000..cc1fcd7f --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-6c7faf.html @@ -0,0 +1,1444 @@ + + + +document-saver.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:tests/document-saver.c
Warning:line 68, column 12
Using a fixed address is not portable because that address will probably not be valid in all environments or platforms
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name document-saver.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/tests -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I .. -I ../pluma -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/gtksourceview-4 -I /usr/include/libpeas-1.0 -I /usr/include/gobject-introspection-1.0 -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/rootdir/tests -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-10-22-114445-13211-1 -x c document-saver.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * document-saver.c
3 * This file is part of pluma
4 *
5 * Copyright (C) 2010 - Jesse van den Kieboom
6 * Copyright (C) 2012-2021 MATE Developers
7 *
8 * pluma is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * pluma is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with pluma; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301 USA
22 */
23
24#include "pluma-document-loader.h"
25#include <gio/gio.h>
26#include <gtk/gtk.h>
27#include <glib.h>
28#include <glib/gprintf.h>
29#include <string.h>
30#include <sys/stat.h>
31
32/* linux/bsd has it. others such as Solaris, do not */
33#ifndef ACCESSPERMS((0400|0200|0100)|((0400|0200|0100) >> 3)|(((0400|0200|
0100) >> 3) >> 3))
34#define ACCESSPERMS((0400|0200|0100)|((0400|0200|0100) >> 3)|(((0400|0200|
0100) >> 3) >> 3))
(S_IRWXU(0400|0200|0100)|S_IRWXG((0400|0200|0100) >> 3)|S_IRWXO(((0400|0200|0100) >> 3) >> 3))
35#endif
36
37#define DEFAULT_LOCAL_URI"/tmp/pluma-document-saver-test.txt" "/tmp/pluma-document-saver-test.txt"
38#define DEFAULT_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-test.txt" "sftp://localhost/tmp/pluma-document-saver-test.txt"
39#define DEFAULT_CONTENT"hello world!" "hello world!"
40#define DEFAULT_CONTENT_RESULT"hello world!\n" "hello world!\n"
41
42#define UNOWNED_LOCAL_DIRECTORY"/tmp/pluma-document-saver-unowned" "/tmp/pluma-document-saver-unowned"
43#define UNOWNED_LOCAL_URI"/tmp/pluma-document-saver-unowned/pluma-document-saver-test.txt" "/tmp/pluma-document-saver-unowned/pluma-document-saver-test.txt"
44
45#define UNOWNED_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-unowned/pluma-document-saver-test.txt" "sftp://localhost/tmp/pluma-document-saver-unowned/pluma-document-saver-test.txt"
46
47#define UNOWNED_GROUP_LOCAL_URI"/tmp/pluma-document-saver-unowned-group.txt" "/tmp/pluma-document-saver-unowned-group.txt"
48#define UNOWNED_GROUP_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-unowned-group.txt" "sftp://localhost/tmp/pluma-document-saver-unowned-group.txt"
49
50static gboolean test_completed;
51static gboolean mount_completed;
52static gboolean mount_success;
53
54typedef struct
55{
56 gchar *uri;
57 const gchar *test_contents;
58 gpointer data;
59} SaverTestData;
60
61static SaverTestData *
62saver_test_data_new (const gchar *uri, const gchar *test_contents, gpointer data)
63{
64 SaverTestData *ret = g_slice_new (SaverTestData)((SaverTestData*) g_slice_alloc (sizeof (SaverTestData)));
65
66 ret->uri = g_strdup (uri)g_strdup_inline (uri);
67 ret->test_contents = test_contents;
68 ret->data = data;
12
Using a fixed address is not portable because that address will probably not be valid in all environments or platforms
69
70 return ret;
71}
72
73static void
74saver_test_data_free (SaverTestData *data)
75{
76 if (data == NULL((void*)0))
77 {
78 return;
79 }
80
81 g_free (data->uri);
82 g_slice_free (SaverTestData, data)do { if (1) g_slice_free1 (sizeof (SaverTestData), (data)); else
(void) ((SaverTestData*) 0 == (data)); } while (0)
;
83}
84
85static PlumaDocument *
86create_document (const gchar *contents)
87{
88 PlumaDocument *document = pluma_document_new ();
89
90 gtk_text_buffer_set_text (GTK_TEXT_BUFFER (document)((((GtkTextBuffer*) (void *) ((document))))), contents, -1);
91 return document;
92}
93
94static void
95complete_test_error (PlumaDocument *document,
96 GError *error,
97 SaverTestData *data)
98{
99 g_assert_no_error (error)do { if (error) g_assertion_message_error (((gchar*) 0), "document-saver.c"
, 99, ((const char*) (__func__)), "error", error, 0, 0); } while
(0)
;
100}
101
102static const gchar *
103read_file (const gchar *uri)
104{
105 GFile *file = g_file_new_for_commandline_arg (uri);
106 GError *error = NULL((void*)0);
107 static gchar buffer[4096];
108 gsize read;
109
110 GInputStream *stream = G_INPUT_STREAM (g_file_read (file, NULL, &error))((((GInputStream*) (void *) ((g_file_read (file, ((void*)0), &
error))))))
;
111
112 g_assert_no_error (error)do { if (error) g_assertion_message_error (((gchar*) 0), "document-saver.c"
, 112, ((const char*) (__func__)), "error", error, 0, 0); } while
(0)
;
113
114 g_input_stream_read_all (stream, buffer, sizeof (buffer) - 1, &read, NULL((void*)0), &error);
115 g_assert_no_error (error)do { if (error) g_assertion_message_error (((gchar*) 0), "document-saver.c"
, 115, ((const char*) (__func__)), "error", error, 0, 0); } while
(0)
;
116
117 buffer[read] = '\0';
118
119 g_input_stream_close (stream, NULL((void*)0), NULL((void*)0));
120
121 g_object_unref (stream);
122 g_object_unref (file);
123
124 return buffer;
125}
126
127static void
128complete_test (PlumaDocument *document,
129 GError *error,
130 SaverTestData *data)
131{
132 test_completed = TRUE(!(0));
133
134 if (data && data->test_contents && data->uri)
135 {
136 g_assert_cmpstr (data->test_contents, ==, read_file (data->uri))do { const char *__s1 = (data->test_contents), *__s2 = (read_file
(data->uri)); if (g_strcmp0 (__s1, __s2) == 0) ; else g_assertion_message_cmpstr
(((gchar*) 0), "document-saver.c", 136, ((const char*) (__func__
)), "data->test_contents" " " "==" " " "read_file (data->uri)"
, __s1, "==", __s2); } while (0)
;
137 }
138}
139
140static void
141mount_ready_callback (GObject *object,
142 GAsyncResult *result,
143 gpointer data)
144{
145 GError *error = NULL((void*)0);
146 mount_success = g_file_mount_enclosing_volume_finish (G_FILE (object)((((GFile*) (void *) ((object))))),
147 result,
148 &error);
149
150 if (error && error->code == G_IO_ERROR_ALREADY_MOUNTED)
151 {
152 mount_success = TRUE(!(0));
153 g_error_free (error);
154 }
155 else
156 {
157 g_assert_no_error (error)do { if (error) g_assertion_message_error (((gchar*) 0), "document-saver.c"
, 157, ((const char*) (__func__)), "error", error, 0, 0); } while
(0)
;
158 }
159
160 mount_completed = TRUE(!(0));
161}
162
163static gboolean
164ensure_mounted (GFile *file)
165{
166 GMountOperation *mo;
167
168 mount_success = FALSE(0);
169 mount_completed = FALSE(0);
170
171 if (g_file_is_native (file))
172 {
173 return TRUE(!(0));
174 }
175
176 mo = gtk_mount_operation_new (NULL((void*)0));
177
178 g_file_mount_enclosing_volume (file,
179 G_MOUNT_MOUNT_NONE,
180 mo,
181 NULL((void*)0),
182 mount_ready_callback,
183 NULL((void*)0));
184
185 while (!mount_completed)
186 {
187 g_main_context_iteration (NULL((void*)0), TRUE(!(0)));
188 }
189
190 g_object_unref (mo);
191
192 return mount_success;
193}
194
195static void
196test_saver (const gchar *filename_or_uri,
197 const gchar *contents,
198 PlumaDocumentNewlineType newline_type,
199 PlumaDocumentSaveFlags save_flags,
200 GCallback saved_callback,
201 SaverTestData *data)
202{
203 GFile *file;
204 gchar *uri;
205 PlumaDocument *document;
206 gboolean existed;
207
208 document = create_document (contents);
209 pluma_document_set_newline_type (document, newline_type);
210
211 g_signal_connect (document, "saved", G_CALLBACK (complete_test_error), data)g_signal_connect_data ((document), ("saved"), (((GCallback) (
complete_test_error))), (data), ((void*)0), (GConnectFlags) 0
)
;
212
213 if (saved_callback)
214 {
215 g_signal_connect (document, "saved", saved_callback, data)g_signal_connect_data ((document), ("saved"), (saved_callback
), (data), ((void*)0), (GConnectFlags) 0)
;
216 }
217
218 g_signal_connect_after (document, "saved", G_CALLBACK (complete_test), data)g_signal_connect_data ((document), ("saved"), (((GCallback) (
complete_test))), (data), ((void*)0), G_CONNECT_AFTER)
;
219
220 test_completed = FALSE(0);
221
222 file = g_file_new_for_commandline_arg (filename_or_uri);
223 uri = g_file_get_uri (file);
224 existed = g_file_query_exists (file, NULL((void*)0));
225
226 ensure_mounted (file);
227
228 pluma_document_save_as (document, uri, pluma_encoding_get_utf8 (), save_flags);
229
230 while (!test_completed)
231 {
232 g_main_context_iteration (NULL((void*)0), TRUE(!(0)));
233 }
234
235 if (!existed)
236 {
237 g_file_delete (file, NULL((void*)0), NULL((void*)0));
238 }
239
240 g_free (uri);
241 g_object_unref (file);
242
243 saver_test_data_free (data);
244}
245
246typedef struct
247{
248 PlumaDocumentNewlineType type;
249 const gchar *text;
250 const gchar *result;
251} NewLineTestData;
252
253static NewLineTestData newline_test_data[] = {
254 {PLUMA_DOCUMENT_NEWLINE_TYPE_LF, "\nhello\nworld", "\nhello\nworld\n"},
255 {PLUMA_DOCUMENT_NEWLINE_TYPE_LF, "\nhello\nworld\n", "\nhello\nworld\n\n"},
256 {PLUMA_DOCUMENT_NEWLINE_TYPE_LF, "\nhello\nworld\n\n", "\nhello\nworld\n\n\n"},
257 {PLUMA_DOCUMENT_NEWLINE_TYPE_LF, "\r\nhello\r\nworld", "\nhello\nworld\n"},
258 {PLUMA_DOCUMENT_NEWLINE_TYPE_LF, "\r\nhello\r\nworld\r\n", "\nhello\nworld\n\n"},
259 {PLUMA_DOCUMENT_NEWLINE_TYPE_LF, "\rhello\rworld", "\nhello\nworld\n"},
260 {PLUMA_DOCUMENT_NEWLINE_TYPE_LF, "\rhello\rworld\r", "\nhello\nworld\n\n"},
261 {PLUMA_DOCUMENT_NEWLINE_TYPE_LF, "\nhello\r\nworld", "\nhello\nworld\n"},
262 {PLUMA_DOCUMENT_NEWLINE_TYPE_LF, "\nhello\r\nworld\r", "\nhello\nworld\n\n"},
263
264 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR_LF, "\nhello\nworld", "\r\nhello\r\nworld\r\n"},
265 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR_LF, "\nhello\nworld\n", "\r\nhello\r\nworld\r\n\r\n"},
266 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR_LF, "\nhello\nworld\n\n", "\r\nhello\r\nworld\r\n\r\n\r\n"},
267 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR_LF, "\r\nhello\r\nworld", "\r\nhello\r\nworld\r\n"},
268 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR_LF, "\r\nhello\r\nworld\r\n", "\r\nhello\r\nworld\r\n\r\n"},
269 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR_LF, "\rhello\rworld", "\r\nhello\r\nworld\r\n"},
270 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR_LF, "\rhello\rworld\r", "\r\nhello\r\nworld\r\n\r\n"},
271 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR_LF, "\nhello\r\nworld", "\r\nhello\r\nworld\r\n"},
272 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR_LF, "\nhello\r\nworld\r", "\r\nhello\r\nworld\r\n\r\n"},
273
274 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR, "\nhello\nworld", "\rhello\rworld\r"},
275 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR, "\nhello\nworld\n", "\rhello\rworld\r\r"},
276 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR, "\nhello\nworld\n\n", "\rhello\rworld\r\r\r"},
277 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR, "\r\nhello\r\nworld", "\rhello\rworld\r"},
278 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR, "\r\nhello\r\nworld\r\n", "\rhello\rworld\r\r"},
279 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR, "\rhello\rworld", "\rhello\rworld\r"},
280 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR, "\rhello\rworld\r", "\rhello\rworld\r\r"},
281 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR, "\nhello\r\nworld", "\rhello\rworld\r"},
282 {PLUMA_DOCUMENT_NEWLINE_TYPE_CR, "\nhello\r\nworld\r", "\rhello\rworld\r\r"}
283};
284
285static void
286test_new_line (const gchar *filename, PlumaDocumentSaveFlags save_flags)
287{
288 gint i;
289 gint num = sizeof (newline_test_data) / sizeof (NewLineTestData);
290
291 for (i = 0; i < num; ++i)
292 {
293 NewLineTestData *nt = &(newline_test_data[i]);
294
295 test_saver (filename,
296 nt->text,
297 nt->type,
298 save_flags,
299 NULL((void*)0),
300 saver_test_data_new (filename, nt->result, NULL((void*)0)));
301 }
302}
303
304static void
305test_local_newline ()
306{
307 test_new_line (DEFAULT_LOCAL_URI"/tmp/pluma-document-saver-test.txt", 0);
308}
309
310static void
311test_local ()
312{
313 test_saver (DEFAULT_LOCAL_URI"/tmp/pluma-document-saver-test.txt",
314 "hello world",
315 PLUMA_DOCUMENT_NEWLINE_TYPE_LF,
316 0,
317 NULL((void*)0),
318 saver_test_data_new (DEFAULT_LOCAL_URI"/tmp/pluma-document-saver-test.txt", "hello world\n", NULL((void*)0)));
319
320 test_saver (DEFAULT_LOCAL_URI"/tmp/pluma-document-saver-test.txt",
321 "hello world\r\n",
322 PLUMA_DOCUMENT_NEWLINE_TYPE_LF,
323 0,
324 NULL((void*)0),
325 saver_test_data_new (DEFAULT_LOCAL_URI"/tmp/pluma-document-saver-test.txt", "hello world\n\n", NULL((void*)0)));
326
327 test_saver (DEFAULT_LOCAL_URI"/tmp/pluma-document-saver-test.txt",
328 "hello world\n",
329 PLUMA_DOCUMENT_NEWLINE_TYPE_LF,
330 0,
331 NULL((void*)0),
332 saver_test_data_new (DEFAULT_LOCAL_URI"/tmp/pluma-document-saver-test.txt", "hello world\n\n", NULL((void*)0)));
333}
334
335static void
336test_remote_newline ()
337{
338 test_new_line (DEFAULT_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-test.txt", 0);
339}
340
341static void
342test_remote ()
343{
344 test_saver (DEFAULT_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-test.txt",
345 "hello world",
346 PLUMA_DOCUMENT_NEWLINE_TYPE_LF,
347 0,
348 NULL((void*)0),
349 saver_test_data_new (DEFAULT_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-test.txt", "hello world\n", NULL((void*)0)));
350
351 test_saver (DEFAULT_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-test.txt",
352 "hello world\r\n",
353 PLUMA_DOCUMENT_NEWLINE_TYPE_LF,
354 0,
355 NULL((void*)0),
356 saver_test_data_new (DEFAULT_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-test.txt", "hello world\n\n", NULL((void*)0)));
357
358 test_saver (DEFAULT_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-test.txt",
359 "hello world\n",
360 PLUMA_DOCUMENT_NEWLINE_TYPE_LF,
361 0,
362 NULL((void*)0),
363 saver_test_data_new (DEFAULT_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-test.txt", "hello world\n\n", NULL((void*)0)));
364}
365
366static void
367check_permissions (GFile *file,
368 guint permissions)
369{
370 GError *error = NULL((void*)0);
371 GFileInfo *info;
372
373 info = g_file_query_info (file,
374 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
375 G_FILE_QUERY_INFO_NONE,
376 NULL((void*)0),
377 &error);
378
379 g_assert_no_error (error)do { if (error) g_assertion_message_error (((gchar*) 0), "document-saver.c"
, 379, ((const char*) (__func__)), "error", error, 0, 0); } while
(0)
;
380
381 g_assert_cmpint (permissions,do { gint64 __n1 = (permissions), __n2 = (g_file_info_get_attribute_uint32
(info, "unix::mode") & ((0400|0200|0100)|((0400|0200|0100
) >> 3)|(((0400|0200|0100) >> 3) >> 3))); if
(__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0
), "document-saver.c", 383, ((const char*) (__func__)), "permissions"
" " "==" " " "g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE) & ACCESSPERMS"
, (long double) __n1, "==", (long double) __n2, 'i'); } while
(0)
382 ==,do { gint64 __n1 = (permissions), __n2 = (g_file_info_get_attribute_uint32
(info, "unix::mode") & ((0400|0200|0100)|((0400|0200|0100
) >> 3)|(((0400|0200|0100) >> 3) >> 3))); if
(__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0
), "document-saver.c", 383, ((const char*) (__func__)), "permissions"
" " "==" " " "g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE) & ACCESSPERMS"
, (long double) __n1, "==", (long double) __n2, 'i'); } while
(0)
383 g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE) & ACCESSPERMS)do { gint64 __n1 = (permissions), __n2 = (g_file_info_get_attribute_uint32
(info, "unix::mode") & ((0400|0200|0100)|((0400|0200|0100
) >> 3)|(((0400|0200|0100) >> 3) >> 3))); if
(__n1 == __n2) ; else g_assertion_message_cmpnum (((gchar*) 0
), "document-saver.c", 383, ((const char*) (__func__)), "permissions"
" " "==" " " "g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE) & ACCESSPERMS"
, (long double) __n1, "==", (long double) __n2, 'i'); } while
(0)
;
384
385 g_object_unref (info);
386}
387
388static void
389check_permissions_saved (PlumaDocument *document,
390 GError *error,
391 SaverTestData *data)
392{
393 guint permissions = (guint)GPOINTER_TO_INT (data->data)((gint) (glong) (data->data));
394 GFile *file = pluma_document_get_location (document);
395
396 check_permissions (file, permissions);
397
398 g_object_unref (file);
399}
400
401static void
402test_permissions (const gchar *uri,
403 guint permissions)
404{
405 GError *error = NULL((void*)0);
406 GFile *file = g_file_new_for_commandline_arg (uri);
407 GFileOutputStream *stream;
408 GFileInfo *info;
409 guint mode;
410
411 g_file_delete (file, NULL((void*)0), NULL((void*)0));
412 stream = g_file_create (file, 0, NULL((void*)0), &error);
413
414 g_assert_no_error (error)do { if (error) g_assertion_message_error (((gchar*) 0), "document-saver.c"
, 414, ((const char*) (__func__)), "error", error, 0, 0); } while
(0)
;
2
Assuming 'error' is null
3
Taking false branch
4
Loop condition is false. Exiting loop
415
416 g_output_stream_close (G_OUTPUT_STREAM (stream)((((GOutputStream*) (void *) ((stream))))), NULL((void*)0), NULL((void*)0));
417 g_object_unref (stream);
418
419 info = g_file_query_info (file,
420 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
421 G_FILE_QUERY_INFO_NONE,
422 NULL((void*)0),
423 &error);
424
425 g_assert_no_error (error)do { if (error) g_assertion_message_error (((gchar*) 0), "document-saver.c"
, 425, ((const char*) (__func__)), "error", error, 0, 0); } while
(0)
;
5
Assuming 'error' is null
6
Taking false branch
7
Loop condition is false. Exiting loop
426
427 mode = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
428 g_object_unref (info);
429
430 g_file_set_attribute_uint32 (file,
431 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
432 (mode & ~ACCESSPERMS((0400|0200|0100)|((0400|0200|0100) >> 3)|(((0400|0200|
0100) >> 3) >> 3))
) | permissions,
433 G_FILE_QUERY_INFO_NONE,
434 NULL((void*)0),
435 &error);
436 g_assert_no_error (error)do { if (error) g_assertion_message_error (((gchar*) 0), "document-saver.c"
, 436, ((const char*) (__func__)), "error", error, 0, 0); } while
(0)
;
8
Assuming 'error' is null
9
Taking false branch
10
Loop condition is false. Exiting loop
437
438 check_permissions (file, permissions);
439
440 test_saver (uri,
441 DEFAULT_CONTENT"hello world!",
442 PLUMA_DOCUMENT_NEWLINE_TYPE_LF,
443 0,
444 G_CALLBACK (check_permissions_saved)((GCallback) (check_permissions_saved)),
445 saver_test_data_new (uri,
11
Calling 'saver_test_data_new'
446 DEFAULT_CONTENT_RESULT"hello world!\n",
447 GINT_TO_POINTER ((gint)permissions)((gpointer) (glong) ((gint)permissions))));
448
449 g_file_delete (file, NULL((void*)0), NULL((void*)0));
450 g_object_unref (file);
451}
452
453static void
454test_local_permissions ()
455{
456 test_permissions (DEFAULT_LOCAL_URI"/tmp/pluma-document-saver-test.txt", 0600);
457 test_permissions (DEFAULT_LOCAL_URI"/tmp/pluma-document-saver-test.txt", 0660);
458 test_permissions (DEFAULT_LOCAL_URI"/tmp/pluma-document-saver-test.txt", 0666);
459 test_permissions (DEFAULT_LOCAL_URI"/tmp/pluma-document-saver-test.txt", 0760);
460}
461
462static void
463test_local_unowned_directory ()
464{
465 test_saver (UNOWNED_LOCAL_URI"/tmp/pluma-document-saver-unowned/pluma-document-saver-test.txt",
466 DEFAULT_CONTENT"hello world!",
467 PLUMA_DOCUMENT_NEWLINE_TYPE_LF,
468 0,
469 NULL((void*)0),
470 saver_test_data_new (UNOWNED_LOCAL_URI"/tmp/pluma-document-saver-unowned/pluma-document-saver-test.txt",
471 DEFAULT_CONTENT_RESULT"hello world!\n",
472 NULL((void*)0)));
473}
474
475static void
476test_remote_unowned_directory ()
477{
478 test_saver (UNOWNED_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-unowned/pluma-document-saver-test.txt",
479 DEFAULT_CONTENT"hello world!",
480 PLUMA_DOCUMENT_NEWLINE_TYPE_LF,
481 0,
482 NULL((void*)0),
483 saver_test_data_new (UNOWNED_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-unowned/pluma-document-saver-test.txt",
484 DEFAULT_CONTENT_RESULT"hello world!\n",
485 NULL((void*)0)));
486}
487
488static void
489test_remote_permissions ()
490{
491 test_permissions (DEFAULT_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-test.txt", 0600);
1
Calling 'test_permissions'
492 test_permissions (DEFAULT_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-test.txt", 0660);
493 test_permissions (DEFAULT_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-test.txt", 0666);
494 test_permissions (DEFAULT_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-test.txt", 0760);
495}
496
497static void
498test_unowned_group_permissions (PlumaDocument *document,
499 GError *error,
500 SaverTestData *data)
501{
502 GFile *file = g_file_new_for_commandline_arg (data->uri);
503 GError *err = NULL((void*)0);
504 const gchar *group;
505 guint32 mode;
506
507 GFileInfo *info = g_file_query_info (file,
508 G_FILE_ATTRIBUTE_OWNER_GROUP"owner::group" ","
509 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
510 G_FILE_QUERY_INFO_NONE,
511 NULL((void*)0),
512 &err);
513
514 g_assert_no_error (err)do { if (err) g_assertion_message_error (((gchar*) 0), "document-saver.c"
, 514, ((const char*) (__func__)), "err", err, 0, 0); } while
(0)
;
515
516 group = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP"owner::group");
517 g_assert_cmpstr (group, ==, "root")do { const char *__s1 = (group), *__s2 = ("root"); if (g_strcmp0
(__s1, __s2) == 0) ; else g_assertion_message_cmpstr (((gchar
*) 0), "document-saver.c", 517, ((const char*) (__func__)), "group"
" " "==" " " "\"root\"", __s1, "==", __s2); } while (0)
;
518
519 mode = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode");
520
521 g_assert_cmpint (mode & ACCESSPERMS, ==, 0660)do { gint64 __n1 = (mode & ((0400|0200|0100)|((0400|0200|
0100) >> 3)|(((0400|0200|0100) >> 3) >> 3))
), __n2 = (0660); if (__n1 == __n2) ; else g_assertion_message_cmpnum
(((gchar*) 0), "document-saver.c", 521, ((const char*) (__func__
)), "mode & ACCESSPERMS" " " "==" " " "0660", (long double
) __n1, "==", (long double) __n2, 'i'); } while (0)
;
522
523 g_object_unref (file);
524 g_object_unref (info);
525}
526
527static void
528test_unowned_group (const gchar *uri)
529{
530 test_saver (uri,
531 DEFAULT_CONTENT"hello world!",
532 PLUMA_DOCUMENT_NEWLINE_TYPE_LF,
533 0,
534 G_CALLBACK (test_unowned_group_permissions)((GCallback) (test_unowned_group_permissions)),
535 saver_test_data_new (uri,
536 DEFAULT_CONTENT_RESULT"hello world!\n",
537 NULL((void*)0)));
538}
539
540static void
541test_local_unowned_group ()
542{
543 test_unowned_group (UNOWNED_GROUP_LOCAL_URI"/tmp/pluma-document-saver-unowned-group.txt");
544}
545
546static void
547test_remote_unowned_group ()
548{
549 test_unowned_group (UNOWNED_GROUP_REMOTE_URI"sftp://localhost/tmp/pluma-document-saver-unowned-group.txt");
550}
551
552static gboolean
553check_unowned_directory ()
554{
555 GFile *unowned = g_file_new_for_path (UNOWNED_LOCAL_DIRECTORY"/tmp/pluma-document-saver-unowned");
556 GFile *unowned_file;
557 GFileInfo *info;
558 GError *error = NULL((void*)0);
559
560 g_printf ("*** Checking for unowned directory test... ");
561
562 info = g_file_query_info (unowned,
563 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write",
564 G_FILE_QUERY_INFO_NONE,
565 NULL((void*)0),
566 &error);
567
568 if (error)
569 {
570 g_object_unref (unowned);
571 g_printf ("NO: directory does not exist\n");
572
573 g_error_free (error);
574 return FALSE(0);
575 }
576
577 if (g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write"))
578 {
579 g_object_unref (unowned);
580
581 g_printf ("NO: directory is writable\n");
582 g_object_unref (info);
583 return FALSE(0);
584 }
585
586 g_object_unref (info);
587 g_object_unref (unowned);
588
589 unowned_file = g_file_new_for_commandline_arg (UNOWNED_LOCAL_URI"/tmp/pluma-document-saver-unowned/pluma-document-saver-test.txt");
590
591 info = g_file_query_info (unowned_file,
592 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write",
593 G_FILE_QUERY_INFO_NONE,
594 NULL((void*)0),
595 &error);
596
597 if (error)
598 {
599 g_object_unref (unowned_file);
600 g_error_free (error);
601
602 g_printf ("NO: file does not exist\n");
603 return FALSE(0);
604 }
605
606 if (!g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write"))
607 {
608 g_object_unref (unowned_file);
609
610 g_printf ("NO: file is not writable\n");
611 g_object_unref (info);
612 return FALSE(0);
613 }
614
615 g_object_unref (info);
616 g_object_unref (unowned_file);
617
618 g_printf ("YES\n");
619 return TRUE(!(0));
620}
621
622static gboolean
623check_unowned_group ()
624{
625 GFile *unowned = g_file_new_for_path (UNOWNED_GROUP_LOCAL_URI"/tmp/pluma-document-saver-unowned-group.txt");
626 GFileInfo *info;
627 GError *error = NULL((void*)0);
628
629 g_printf ("*** Checking for unowned group test... ");
630
631 info = g_file_query_info (unowned,
632 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write" ","
633 G_FILE_ATTRIBUTE_OWNER_GROUP"owner::group" ","
634 G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode",
635 G_FILE_QUERY_INFO_NONE,
636 NULL((void*)0),
637 &error);
638
639 if (error)
640 {
641 g_object_unref (unowned);
642 g_printf ("NO: file does not exist\n");
643
644 g_error_free (error);
645 return FALSE(0);
646 }
647
648 if (!g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE"access::can-write"))
649 {
650 g_object_unref (unowned);
651
652 g_printf ("NO: file is not writable\n");
653 g_object_unref (info);
654 return FALSE(0);
655 }
656
657 if (g_strcmp0 (g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP"owner::group"),
658 "root") != 0)
659 {
660 g_object_unref (unowned);
661
662 g_printf ("NO: group is not root (%s)\n", g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP"owner::group"));
663 g_object_unref (info);
664 return FALSE(0);
665 }
666
667 if ((g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE"unix::mode") & ACCESSPERMS((0400|0200|0100)|((0400|0200|0100) >> 3)|(((0400|0200|
0100) >> 3) >> 3))
) != 0660)
668 {
669 g_object_unref (unowned);
670
671 g_printf ("NO: file has wrong permissions\n");
672 g_object_unref (info);
673 return FALSE(0);
674 }
675
676 g_object_unref (info);
677 g_object_unref (unowned);
678
679 g_printf ("YES\n");
680 return TRUE(!(0));
681}
682
683int main (int argc,
684 char *argv[])
685{
686 gboolean have_unowned;
687 gboolean have_unowned_group;
688
689 g_test_init (&argc, &argv, NULL((void*)0));
690
691 g_printf ("\n***\n");
692 have_unowned = check_unowned_directory ();
693 have_unowned_group = check_unowned_group ();
694 g_printf ("***\n\n");
695
696 g_test_add_func ("/document-saver/local", test_local);
697 g_test_add_func ("/document-saver/local-new-line", test_local_newline);
698
699 if (have_unowned)
700 {
701 g_test_add_func ("/document-saver/local-unowned-directory", test_local_unowned_directory);
702 }
703
704 g_test_add_func ("/document-saver/remote", test_remote);
705 g_test_add_func ("/document-saver/remote-new-line", test_remote_newline);
706
707
708 if (have_unowned)
709 {
710 g_test_add_func ("/document-saver/remote-unowned-directory", test_remote_unowned_directory);
711 }
712
713 if (have_unowned_group)
714 {
715 /* FIXME: there is a bug in gvfs sftp which doesn't pass this test */
716 /* g_test_add_func ("/document-saver/remote-unowned-group", test_remote_unowned_group); */
717 }
718
719 g_test_add_func ("/document-saver/local-permissions", test_local_permissions);
720
721 if (have_unowned_group)
722 {
723 g_test_add_func ("/document-saver/local-unowned-group", test_local_unowned_group);
724 }
725
726 g_test_add_func ("/document-saver/remote-permissions", test_remote_permissions);
727
728 return g_test_run ();
729}
diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-731a91.html b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-731a91.html new file mode 100644 index 00000000..9c69708e --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-731a91.html @@ -0,0 +1,4342 @@ + + + +pluma-file-browser-store.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:plugins/filebrowser/pluma-file-browser-store.c
Warning:line 1110, column 21
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pluma-file-browser-store.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/plugins/filebrowser -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I ../.. -I ../.. -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/gtksourceview-4 -I /usr/include/libpeas-1.0 -I /usr/include/gobject-introspection-1.0 -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/plugins/filebrowser -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-10-22-114445-13211-1 -x c pluma-file-browser-store.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * pluma-file-browser-store.c - Pluma plugin providing easy file access
3 * from the sidepanel
4 *
5 * Copyright (C) 2006 - Jesse van den Kieboom <jesse@icecrew.nl>
6 * Copyright (C) 2012-2021 MATE Developers
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23#ifdef HAVE_CONFIG_H1
24#include <config.h>
25#endif
26
27#include <string.h>
28#include <glib/gi18n-lib.h>
29#include <gio/gio.h>
30
31#include "pluma-file-browser-store.h"
32#include "pluma-file-browser-enum-types.h"
33#include "pluma-file-browser-error.h"
34#include "pluma-file-browser-utils.h"
35
36#define NODE_IS_DIR(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
(FILE_IS_DIR((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
)
)
37#define NODE_IS_HIDDEN(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
))
(FILE_IS_HIDDEN((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
)
)
38#define NODE_IS_TEXT(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_TEXT
))
(FILE_IS_TEXT((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_TEXT
)
)
39#define NODE_LOADED(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
(FILE_LOADED((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED))
40#define NODE_IS_FILTERED(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED
))
(FILE_IS_FILTERED((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED
)
)
41#define NODE_IS_DUMMY(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
(FILE_IS_DUMMY((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
)
)
42
43#define FILE_BROWSER_NODE_DIR(node)((FileBrowserNodeDir *)(node)) ((FileBrowserNodeDir *)(node))
44
45#define DIRECTORY_LOAD_ITEMS_PER_CALLBACK100 100
46#define STANDARD_ATTRIBUTE_TYPES"standard::type" "," "standard::is-hidden" "," "standard::is-backup"
"," "standard::name" "," "standard::content-type" "," "standard::icon"
G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type" "," \
47 G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN"standard::is-hidden" "," \
48 G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP"standard::is-backup" "," \
49 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name" "," \
50 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE"standard::content-type" "," \
51 G_FILE_ATTRIBUTE_STANDARD_ICON"standard::icon"
52
53typedef struct _FileBrowserNode FileBrowserNode;
54typedef struct _FileBrowserNodeDir FileBrowserNodeDir;
55typedef struct _AsyncData AsyncData;
56typedef struct _AsyncNode AsyncNode;
57
58typedef gint (*SortFunc) (FileBrowserNode * node1,
59 FileBrowserNode * node2);
60
61struct _AsyncData
62{
63 PlumaFileBrowserStore * model;
64 GCancellable * cancellable;
65 gboolean trash;
66 GList * files;
67 GList * iter;
68 gboolean removed;
69};
70
71struct _AsyncNode
72{
73 FileBrowserNodeDir *dir;
74 GCancellable *cancellable;
75 GSList *original_children;
76};
77
78typedef struct {
79 PlumaFileBrowserStore * model;
80 gchar * virtual_root;
81 GMountOperation * operation;
82 GCancellable * cancellable;
83} MountInfo;
84
85struct _FileBrowserNode
86{
87 GFile *file;
88 guint flags;
89 gchar *name;
90
91 GdkPixbuf *icon;
92 GdkPixbuf *emblem;
93
94 FileBrowserNode *parent;
95 gint pos;
96 gboolean inserted;
97};
98
99struct _FileBrowserNodeDir
100{
101 FileBrowserNode node;
102 GSList *children;
103
104 GCancellable *cancellable;
105 GFileMonitor *monitor;
106 PlumaFileBrowserStore *model;
107};
108
109struct _PlumaFileBrowserStorePrivate
110{
111 FileBrowserNode *root;
112 FileBrowserNode *virtual_root;
113 GType column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_NUM];
114
115 PlumaFileBrowserStoreFilterMode filter_mode;
116 PlumaFileBrowserStoreFilterFunc filter_func;
117 gpointer filter_user_data;
118
119 SortFunc sort_func;
120
121 GSList *async_handles;
122 MountInfo *mount_info;
123};
124
125static FileBrowserNode *model_find_node (PlumaFileBrowserStore *model,
126 FileBrowserNode *node,
127 GFile *uri);
128static void model_remove_node (PlumaFileBrowserStore * model,
129 FileBrowserNode * node,
130 GtkTreePath * path,
131 gboolean free_nodes);
132
133static void set_virtual_root_from_node (PlumaFileBrowserStore * model,
134 FileBrowserNode * node);
135
136static void pluma_file_browser_store_iface_init (GtkTreeModelIface * iface);
137static GtkTreeModelFlags pluma_file_browser_store_get_flags (GtkTreeModel * tree_model);
138static gint pluma_file_browser_store_get_n_columns (GtkTreeModel * tree_model);
139static GType pluma_file_browser_store_get_column_type (GtkTreeModel * tree_model,
140 gint index);
141static gboolean pluma_file_browser_store_get_iter (GtkTreeModel * tree_model,
142 GtkTreeIter * iter,
143 GtkTreePath * path);
144static GtkTreePath *pluma_file_browser_store_get_path (GtkTreeModel * tree_model,
145 GtkTreeIter * iter);
146static void pluma_file_browser_store_get_value (GtkTreeModel * tree_model,
147 GtkTreeIter * iter,
148 gint column,
149 GValue * value);
150static gboolean pluma_file_browser_store_iter_next (GtkTreeModel * tree_model,
151 GtkTreeIter * iter);
152static gboolean pluma_file_browser_store_iter_children (GtkTreeModel * tree_model,
153 GtkTreeIter * iter,
154 GtkTreeIter * parent);
155static gboolean pluma_file_browser_store_iter_has_child (GtkTreeModel * tree_model,
156 GtkTreeIter * iter);
157static gint pluma_file_browser_store_iter_n_children (GtkTreeModel * tree_model,
158 GtkTreeIter * iter);
159static gboolean pluma_file_browser_store_iter_nth_child (GtkTreeModel * tree_model,
160 GtkTreeIter * iter,
161 GtkTreeIter * parent,
162 gint n);
163static gboolean pluma_file_browser_store_iter_parent (GtkTreeModel * tree_model,
164 GtkTreeIter * iter,
165 GtkTreeIter * child);
166static void pluma_file_browser_store_row_inserted (GtkTreeModel * tree_model,
167 GtkTreePath * path,
168 GtkTreeIter * iter);
169
170static void pluma_file_browser_store_drag_source_init (GtkTreeDragSourceIface * iface);
171static gboolean pluma_file_browser_store_row_draggable (GtkTreeDragSource * drag_source,
172 GtkTreePath * path);
173static gboolean pluma_file_browser_store_drag_data_delete (GtkTreeDragSource * drag_source,
174 GtkTreePath * path);
175static gboolean pluma_file_browser_store_drag_data_get (GtkTreeDragSource * drag_source,
176 GtkTreePath * path,
177 GtkSelectionData * selection_data);
178
179static void file_browser_node_free (PlumaFileBrowserStore * model,
180 FileBrowserNode * node);
181static void model_add_node (PlumaFileBrowserStore * model,
182 FileBrowserNode * child,
183 FileBrowserNode * parent);
184static void model_clear (PlumaFileBrowserStore * model,
185 gboolean free_nodes);
186static gint model_sort_default (FileBrowserNode * node1,
187 FileBrowserNode * node2);
188static void model_check_dummy (PlumaFileBrowserStore * model,
189 FileBrowserNode * node);
190static void next_files_async (GFileEnumerator * enumerator,
191 AsyncNode * async);
192
193static void delete_files (AsyncData *data);
194
195G_DEFINE_DYNAMIC_TYPE_EXTENDED (PlumaFileBrowserStore, pluma_file_browser_store,static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
196 G_TYPE_OBJECT,static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
197 0,static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
198 G_ADD_PRIVATE_DYNAMIC (PlumaFileBrowserStore)static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
199 G_IMPLEMENT_INTERFACE_DYNAMIC (GTK_TYPE_TREE_MODEL,static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
200 pluma_file_browser_store_iface_init)static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
201 G_IMPLEMENT_INTERFACE_DYNAMIC (GTK_TYPE_TREE_DRAG_SOURCE,static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
202 pluma_file_browser_store_drag_source_init))static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
203
204/* Properties */
205enum {
206 PROP_0,
207
208 PROP_ROOT,
209 PROP_VIRTUAL_ROOT,
210 PROP_FILTER_MODE
211};
212
213/* Signals */
214enum
215{
216 BEGIN_LOADING,
217 END_LOADING,
218 ERROR,
219 NO_TRASH,
220 RENAME,
221 BEGIN_REFRESH,
222 END_REFRESH,
223 UNLOAD,
224 NUM_SIGNALS
225};
226
227static guint model_signals[NUM_SIGNALS] = { 0 };
228
229static void
230cancel_mount_operation (PlumaFileBrowserStore *obj)
231{
232 if (obj->priv->mount_info != NULL((void*)0))
233 {
234 obj->priv->mount_info->model = NULL((void*)0);
235 g_cancellable_cancel (obj->priv->mount_info->cancellable);
236 obj->priv->mount_info = NULL((void*)0);
237 }
238}
239
240static void
241pluma_file_browser_store_finalize (GObject * object)
242{
243 PlumaFileBrowserStore *obj = PLUMA_FILE_BROWSER_STORE (object)((((PlumaFileBrowserStore*) (void *) ((object)))));
244 GSList *item;
245
246 /* Free all the nodes */
247 file_browser_node_free (obj, obj->priv->root);
248
249 /* Cancel any asynchronous operations */
250 for (item = obj->priv->async_handles; item; item = item->next)
251 {
252 AsyncData *data = (AsyncData *) (item->data);
253 g_cancellable_cancel (data->cancellable);
254
255 data->removed = TRUE(!(0));
256 }
257
258 cancel_mount_operation (obj);
259
260 g_slist_free (obj->priv->async_handles);
261 G_OBJECT_CLASS (pluma_file_browser_store_parent_class)((((GObjectClass*) (void *) ((pluma_file_browser_store_parent_class
)))))
->finalize (object);
262}
263
264static void
265set_gvalue_from_node (GValue *value,
266 FileBrowserNode *node)
267{
268 gchar * uri;
269
270 if (node == NULL((void*)0) || !node->file) {
271 g_value_set_string (value, NULL((void*)0));
272 } else {
273 uri = g_file_get_uri (node->file);
274 g_value_take_string (value, uri);
275 }
276}
277
278static void
279pluma_file_browser_store_get_property (GObject *object,
280 guint prop_id,
281 GValue *value,
282 GParamSpec *pspec)
283{
284 PlumaFileBrowserStore *obj = PLUMA_FILE_BROWSER_STORE (object)((((PlumaFileBrowserStore*) (void *) ((object)))));
285
286 switch (prop_id)
287 {
288 case PROP_ROOT:
289 set_gvalue_from_node (value, obj->priv->root);
290 break;
291 case PROP_VIRTUAL_ROOT:
292 set_gvalue_from_node (value, obj->priv->virtual_root);
293 break;
294 case PROP_FILTER_MODE:
295 g_value_set_flags (value, obj->priv->filter_mode);
296 break;
297 default:
298 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "pluma-file-browser-store.c", 298, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
299 break;
300 }
301}
302
303static void
304pluma_file_browser_store_set_property (GObject *object,
305 guint prop_id,
306 const GValue *value,
307 GParamSpec *pspec)
308{
309 PlumaFileBrowserStore *obj = PLUMA_FILE_BROWSER_STORE (object)((((PlumaFileBrowserStore*) (void *) ((object)))));
310
311 switch (prop_id)
312 {
313 case PROP_FILTER_MODE:
314 pluma_file_browser_store_set_filter_mode (obj,
315 g_value_get_flags (value));
316 break;
317 default:
318 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "pluma-file-browser-store.c", 318, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
319 break;
320 }
321}
322
323static void
324pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass * klass)
325{
326 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) ((klass)))));
327
328 object_class->finalize = pluma_file_browser_store_finalize;
329
330 object_class->get_property = pluma_file_browser_store_get_property;
331 object_class->set_property = pluma_file_browser_store_set_property;
332
333 g_object_class_install_property (object_class, PROP_ROOT,
334 g_param_spec_string ("root",
335 "Root",
336 "The root uri",
337 NULL((void*)0),
338 G_PARAM_READABLE));
339
340 g_object_class_install_property (object_class, PROP_VIRTUAL_ROOT,
341 g_param_spec_string ("virtual-root",
342 "Virtual Root",
343 "The virtual root uri",
344 NULL((void*)0),
345 G_PARAM_READABLE));
346
347 g_object_class_install_property (object_class, PROP_FILTER_MODE,
348 g_param_spec_flags ("filter-mode",
349 "Filter Mode",
350 "The filter mode",
351 PLUMA_TYPE_FILE_BROWSER_STORE_FILTER_MODE(pluma_file_browser_store_filter_mode_get_type()),
352 pluma_file_browser_store_filter_mode_get_default (),
353 G_PARAM_READWRITE));
354
355 model_signals[BEGIN_LOADING] =
356 g_signal_new ("begin-loading",
357 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
358 G_SIGNAL_RUN_LAST,
359 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, begin_loading)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, begin_loading
))
,
360 NULL((void*)0), NULL((void*)0), NULL((void*)0),
361 G_TYPE_NONE((GType) ((1) << (2))), 1, GTK_TYPE_TREE_ITER(gtk_tree_iter_get_type ()));
362 model_signals[END_LOADING] =
363 g_signal_new ("end-loading",
364 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
365 G_SIGNAL_RUN_LAST,
366 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, end_loading)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, end_loading
))
,
367 NULL((void*)0), NULL((void*)0), NULL((void*)0),
368 G_TYPE_NONE((GType) ((1) << (2))), 1,
369 GTK_TYPE_TREE_ITER(gtk_tree_iter_get_type ()));
370 model_signals[ERROR] =
371 g_signal_new ("error", G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
372 G_SIGNAL_RUN_LAST,
373 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, error)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, error
))
,
374 NULL((void*)0), NULL((void*)0), NULL((void*)0),
375 G_TYPE_NONE((GType) ((1) << (2))), 2, G_TYPE_UINT((GType) ((7) << (2))), G_TYPE_STRING((GType) ((16) << (2))));
376 model_signals[NO_TRASH] =
377 g_signal_new ("no-trash", G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
378 G_SIGNAL_RUN_LAST,
379 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, no_trash)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, no_trash
))
,
380 g_signal_accumulator_true_handled, NULL((void*)0), NULL((void*)0),
381 G_TYPE_BOOLEAN((GType) ((5) << (2))), 1, G_TYPE_POINTER((GType) ((17) << (2))));
382 model_signals[RENAME] =
383 g_signal_new ("rename",
384 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
385 G_SIGNAL_RUN_LAST,
386 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, rename)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, rename
))
,
387 NULL((void*)0), NULL((void*)0), NULL((void*)0),
388 G_TYPE_NONE((GType) ((1) << (2))), 2,
389 G_TYPE_STRING((GType) ((16) << (2))),
390 G_TYPE_STRING((GType) ((16) << (2))));
391 model_signals[BEGIN_REFRESH] =
392 g_signal_new ("begin-refresh",
393 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
394 G_SIGNAL_RUN_LAST,
395 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, begin_refresh)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, begin_refresh
))
,
396 NULL((void*)0), NULL((void*)0), NULL((void*)0),
397 G_TYPE_NONE((GType) ((1) << (2))), 0);
398 model_signals[END_REFRESH] =
399 g_signal_new ("end-refresh",
400 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
401 G_SIGNAL_RUN_LAST,
402 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, end_refresh)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, end_refresh
))
,
403 NULL((void*)0), NULL((void*)0), NULL((void*)0),
404 G_TYPE_NONE((GType) ((1) << (2))), 0);
405 model_signals[UNLOAD] =
406 g_signal_new ("unload",
407 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
408 G_SIGNAL_RUN_LAST,
409 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, unload)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, unload
))
,
410 NULL((void*)0), NULL((void*)0), NULL((void*)0),
411 G_TYPE_NONE((GType) ((1) << (2))), 1,
412 G_TYPE_STRING((GType) ((16) << (2))));
413}
414
415static void
416pluma_file_browser_store_class_finalize (PlumaFileBrowserStoreClass *klass)
417{
418 /* dummy function - used by G_DEFINE_DYNAMIC_TYPE_EXTENDED */
419}
420
421static void
422pluma_file_browser_store_iface_init (GtkTreeModelIface * iface)
423{
424 iface->get_flags = pluma_file_browser_store_get_flags;
425 iface->get_n_columns = pluma_file_browser_store_get_n_columns;
426 iface->get_column_type = pluma_file_browser_store_get_column_type;
427 iface->get_iter = pluma_file_browser_store_get_iter;
428 iface->get_path = pluma_file_browser_store_get_path;
429 iface->get_value = pluma_file_browser_store_get_value;
430 iface->iter_next = pluma_file_browser_store_iter_next;
431 iface->iter_children = pluma_file_browser_store_iter_children;
432 iface->iter_has_child = pluma_file_browser_store_iter_has_child;
433 iface->iter_n_children = pluma_file_browser_store_iter_n_children;
434 iface->iter_nth_child = pluma_file_browser_store_iter_nth_child;
435 iface->iter_parent = pluma_file_browser_store_iter_parent;
436 iface->row_inserted = pluma_file_browser_store_row_inserted;
437}
438
439static void
440pluma_file_browser_store_drag_source_init (GtkTreeDragSourceIface * iface)
441{
442 iface->row_draggable = pluma_file_browser_store_row_draggable;
443 iface->drag_data_delete = pluma_file_browser_store_drag_data_delete;
444 iface->drag_data_get = pluma_file_browser_store_drag_data_get;
445}
446
447static void
448pluma_file_browser_store_init (PlumaFileBrowserStore * obj)
449{
450 obj->priv = pluma_file_browser_store_get_instance_private (obj);
451
452 obj->priv->column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_URI] =
453 G_TYPE_STRING((GType) ((16) << (2)));
454 obj->priv->column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_NAME] =
455 G_TYPE_STRING((GType) ((16) << (2)));
456 obj->priv->column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_FLAGS] =
457 G_TYPE_UINT((GType) ((7) << (2)));
458 obj->priv->column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_ICON] =
459 GDK_TYPE_PIXBUF(gdk_pixbuf_get_type ());
460 obj->priv->column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM] =
461 GDK_TYPE_PIXBUF(gdk_pixbuf_get_type ());
462
463 // Default filter mode is hiding the hidden files
464 obj->priv->filter_mode = pluma_file_browser_store_filter_mode_get_default ();
465 obj->priv->sort_func = model_sort_default;
466}
467
468static gboolean
469node_has_parent (FileBrowserNode * node, FileBrowserNode * parent)
470{
471 if (node->parent == NULL((void*)0))
472 return FALSE(0);
473
474 if (node->parent == parent)
475 return TRUE(!(0));
476
477 return node_has_parent (node->parent, parent);
478}
479
480static gboolean
481node_in_tree (PlumaFileBrowserStore * model, FileBrowserNode * node)
482{
483 return node_has_parent (node, model->priv->virtual_root);
484}
485
486static gboolean
487model_node_visibility (PlumaFileBrowserStore * model,
488 FileBrowserNode * node)
489{
490 if (node == NULL((void*)0))
491 return FALSE(0);
492
493 if (NODE_IS_DUMMY (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
)
494 return !NODE_IS_HIDDEN (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
))
;
495
496 if (node == model->priv->virtual_root)
497 return TRUE(!(0));
498
499 if (!node_has_parent (node, model->priv->virtual_root))
500 return FALSE(0);
501
502 return !NODE_IS_FILTERED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED
))
;
503}
504
505static gboolean
506model_node_inserted (PlumaFileBrowserStore * model,
507 FileBrowserNode * node)
508{
509 return node == model->priv->virtual_root || (model_node_visibility (model, node) && node->inserted);
510}
511
512/* Interface implementation */
513
514static GtkTreeModelFlags
515pluma_file_browser_store_get_flags (GtkTreeModel * tree_model)
516{
517 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_186
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_186 = 1; else _g_boolean_var_186 =
0; _g_boolean_var_186; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((GtkTreeModelFlags) 0); } } while (0)
518 (GtkTreeModelFlags) 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_186
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_186 = 1; else _g_boolean_var_186 =
0; _g_boolean_var_186; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((GtkTreeModelFlags) 0); } } while (0)
;
519
520 return GTK_TREE_MODEL_ITERS_PERSIST;
521}
522
523static gint
524pluma_file_browser_store_get_n_columns (GtkTreeModel * tree_model)
525{
526 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_187
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_187 = 1; else _g_boolean_var_187 =
0; _g_boolean_var_187; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return (0); } } while (0)
;
527
528 return PLUMA_FILE_BROWSER_STORE_COLUMN_NUM;
529}
530
531static GType
532pluma_file_browser_store_get_column_type (GtkTreeModel * tree_model, gint idx)
533{
534 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_188
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_188 = 1; else _g_boolean_var_188 =
0; _g_boolean_var_188; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return (((GType) ((0) << (2)))); } } while (0)
535 G_TYPE_INVALID)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_188
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_188 = 1; else _g_boolean_var_188 =
0; _g_boolean_var_188; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return (((GType) ((0) << (2)))); } } while (0)
;
536 g_return_val_if_fail (idx < PLUMA_FILE_BROWSER_STORE_COLUMN_NUM &&do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_189
; if (idx < PLUMA_FILE_BROWSER_STORE_COLUMN_NUM &&
idx >= 0) _g_boolean_var_189 = 1; else _g_boolean_var_189
= 0; _g_boolean_var_189; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "idx < PLUMA_FILE_BROWSER_STORE_COLUMN_NUM && idx >= 0"
); return (((GType) ((0) << (2)))); } } while (0)
537 idx >= 0, G_TYPE_INVALID)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_189
; if (idx < PLUMA_FILE_BROWSER_STORE_COLUMN_NUM &&
idx >= 0) _g_boolean_var_189 = 1; else _g_boolean_var_189
= 0; _g_boolean_var_189; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "idx < PLUMA_FILE_BROWSER_STORE_COLUMN_NUM && idx >= 0"
); return (((GType) ((0) << (2)))); } } while (0)
;
538
539 return PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))))->priv->column_types[idx];
540}
541
542static gboolean
543pluma_file_browser_store_get_iter (GtkTreeModel * tree_model,
544 GtkTreeIter * iter, GtkTreePath * path)
545{
546 gint * indices, depth, i;
547 FileBrowserNode * node;
548 PlumaFileBrowserStore * model;
549 gint num;
550
551 g_assert (PLUMA_IS_FILE_BROWSER_STORE (tree_model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_190
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_190 = 1; else _g_boolean_var_190 =
0; _g_boolean_var_190; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "pluma-file-browser-store.c", 551, ((const char
*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"); }
while (0)
;
552 g_assert (path != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_191
; if (path != ((void*)0)) _g_boolean_var_191 = 1; else _g_boolean_var_191
= 0; _g_boolean_var_191; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "pluma-file-browser-store.c", 552, ((const char
*) (__func__)), "path != NULL"); } while (0)
;
553
554 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
555 indices = gtk_tree_path_get_indices (path);
556 depth = gtk_tree_path_get_depth (path);
557 node = model->priv->virtual_root;
558
559 for (i = 0; i < depth; ++i) {
560 GSList * item;
561
562 if (node == NULL((void*)0))
563 return FALSE(0);
564
565 num = 0;
566
567 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
568 return FALSE(0);
569
570 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item; item = item->next) {
571 FileBrowserNode * child;
572
573 child = (FileBrowserNode *) (item->data);
574
575 if (model_node_inserted (model, child)) {
576 if (num == indices[i]) {
577 node = child;
578 break;
579 }
580
581 num++;
582 }
583 }
584
585 if (item == NULL((void*)0))
586 return FALSE(0);
587
588 node = (FileBrowserNode *) (item->data);
589 }
590
591 iter->user_data = node;
592 iter->user_data2 = NULL((void*)0);
593 iter->user_data3 = NULL((void*)0);
594
595 return node != NULL((void*)0);
596}
597
598static GtkTreePath *
599pluma_file_browser_store_get_path_real (PlumaFileBrowserStore * model,
600 FileBrowserNode * node)
601{
602 GtkTreePath *path;
603 gint num = 0;
604
605 path = gtk_tree_path_new ();
606
607 while (node != model->priv->virtual_root) {
608 GSList *item;
609
610 if (node->parent == NULL((void*)0)) {
611 gtk_tree_path_free (path);
612 return NULL((void*)0);
613 }
614
615 num = 0;
616
617 for (item = FILE_BROWSER_NODE_DIR (node->parent)((FileBrowserNodeDir *)(node->parent))->children; item; item = item->next) {
618 FileBrowserNode *check;
619
620 check = (FileBrowserNode *) (item->data);
621
622 if (model_node_visibility (model, check) && (check == node || check->inserted)) {
623 if (check == node) {
624 gtk_tree_path_prepend_index (path,
625 num);
626 break;
627 }
628
629 ++num;
630 } else if (check == node) {
631 if (NODE_IS_DUMMY (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
)
632 g_warning ("Dummy not visible???");
633
634 gtk_tree_path_free (path);
635 return NULL((void*)0);
636 }
637 }
638
639 node = node->parent;
640 }
641
642 return path;
643}
644
645static GtkTreePath *
646pluma_file_browser_store_get_path (GtkTreeModel * tree_model,
647 GtkTreeIter * iter)
648{
649 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_192
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_192 = 1; else _g_boolean_var_192 =
0; _g_boolean_var_192; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return (((void*)0)); } } while (0)
;
650 g_return_val_if_fail (iter != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_193
; if (iter != ((void*)0)) _g_boolean_var_193 = 1; else _g_boolean_var_193
= 0; _g_boolean_var_193; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
(((void*)0)); } } while (0)
;
651 g_return_val_if_fail (iter->user_data != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_194
; if (iter->user_data != ((void*)0)) _g_boolean_var_194 = 1
; else _g_boolean_var_194 = 0; _g_boolean_var_194; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return (((void
*)0)); } } while (0)
;
652
653 return pluma_file_browser_store_get_path_real (PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model))))),
654 (FileBrowserNode *) (iter->user_data));
655}
656
657static void
658pluma_file_browser_store_get_value (GtkTreeModel * tree_model,
659 GtkTreeIter * iter,
660 gint column,
661 GValue * value)
662{
663 FileBrowserNode *node;
664
665 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_195
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_195 = 1; else _g_boolean_var_195 =
0; _g_boolean_var_195; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return; } } while (0)
;
666 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_196
; if (iter != ((void*)0)) _g_boolean_var_196 = 1; else _g_boolean_var_196
= 0; _g_boolean_var_196; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
667 g_return_if_fail (iter->user_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_197
; if (iter->user_data != ((void*)0)) _g_boolean_var_197 = 1
; else _g_boolean_var_197 = 0; _g_boolean_var_197; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return; } } while
(0)
;
668
669 node = (FileBrowserNode *) (iter->user_data);
670
671 g_value_init (value, PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))))->priv->column_types[column]);
672
673 switch (column) {
674 case PLUMA_FILE_BROWSER_STORE_COLUMN_URI:
675 set_gvalue_from_node (value, node);
676 break;
677 case PLUMA_FILE_BROWSER_STORE_COLUMN_NAME:
678 g_value_set_string (value, node->name);
679 break;
680 case PLUMA_FILE_BROWSER_STORE_COLUMN_FLAGS:
681 g_value_set_uint (value, node->flags);
682 break;
683 case PLUMA_FILE_BROWSER_STORE_COLUMN_ICON:
684 g_value_set_object (value, node->icon);
685 break;
686 case PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM:
687 g_value_set_object (value, node->emblem);
688 break;
689 default:
690 g_return_if_reached ()do { g_log (((gchar*) 0), G_LOG_LEVEL_CRITICAL, "file %s: line %d (%s): should not be reached"
, "pluma-file-browser-store.c", 690, ((const char*) (__func__
))); return; } while (0)
;
691 }
692}
693
694static gboolean
695pluma_file_browser_store_iter_next (GtkTreeModel * tree_model,
696 GtkTreeIter * iter)
697{
698 PlumaFileBrowserStore * model;
699 FileBrowserNode * node;
700 GSList * item;
701 GSList * first;
702
703 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_198
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_198 = 1; else _g_boolean_var_198 =
0; _g_boolean_var_198; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
704 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_198
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_198 = 1; else _g_boolean_var_198 =
0; _g_boolean_var_198; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
705 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_199
; if (iter != ((void*)0)) _g_boolean_var_199 = 1; else _g_boolean_var_199
= 0; _g_boolean_var_199; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
706 g_return_val_if_fail (iter->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_200
; if (iter->user_data != ((void*)0)) _g_boolean_var_200 = 1
; else _g_boolean_var_200 = 0; _g_boolean_var_200; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return ((0)); }
} while (0)
;
707
708 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
709 node = (FileBrowserNode *) (iter->user_data);
710
711 if (node->parent == NULL((void*)0))
712 return FALSE(0);
713
714 first = g_slist_next (g_slist_find (FILE_BROWSER_NODE_DIR (node->parent)->children, node))((g_slist_find (((FileBrowserNodeDir *)(node->parent))->
children, node)) ? (((GSList *)(g_slist_find (((FileBrowserNodeDir
*)(node->parent))->children, node)))->next) : ((void
*)0))
;
715
716 for (item = first; item; item = item->next) {
717 if (model_node_inserted (model, (FileBrowserNode *) (item->data))) {
718 iter->user_data = item->data;
719 return TRUE(!(0));
720 }
721 }
722
723 return FALSE(0);
724}
725
726static gboolean
727pluma_file_browser_store_iter_children (GtkTreeModel * tree_model,
728 GtkTreeIter * iter,
729 GtkTreeIter * parent)
730{
731 FileBrowserNode * node;
732 PlumaFileBrowserStore * model;
733 GSList * item;
734
735 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_201
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_201 = 1; else _g_boolean_var_201 =
0; _g_boolean_var_201; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
736 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_201
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_201 = 1; else _g_boolean_var_201 =
0; _g_boolean_var_201; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
737 g_return_val_if_fail (parent == NULLdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_202
; if (parent == ((void*)0) || parent->user_data != ((void*
)0)) _g_boolean_var_202 = 1; else _g_boolean_var_202 = 0; _g_boolean_var_202
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "parent == NULL || parent->user_data != NULL"
); return ((0)); } } while (0)
738 || parent->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_202
; if (parent == ((void*)0) || parent->user_data != ((void*
)0)) _g_boolean_var_202 = 1; else _g_boolean_var_202 = 0; _g_boolean_var_202
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "parent == NULL || parent->user_data != NULL"
); return ((0)); } } while (0)
;
739
740 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
741
742 if (parent == NULL((void*)0))
743 node = model->priv->virtual_root;
744 else
745 node = (FileBrowserNode *) (parent->user_data);
746
747 if (node == NULL((void*)0))
748 return FALSE(0);
749
750 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
751 return FALSE(0);
752
753 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item; item = item->next) {
754 if (model_node_inserted (model, (FileBrowserNode *) (item->data))) {
755 iter->user_data = item->data;
756 return TRUE(!(0));
757 }
758 }
759
760 return FALSE(0);
761}
762
763static gboolean
764filter_tree_model_iter_has_child_real (PlumaFileBrowserStore * model,
765 FileBrowserNode * node)
766{
767 GSList *item;
768
769 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
770 return FALSE(0);
771
772 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item; item = item->next) {
773 if (model_node_inserted (model, (FileBrowserNode *) (item->data)))
774 return TRUE(!(0));
775 }
776
777 return FALSE(0);
778}
779
780static gboolean
781pluma_file_browser_store_iter_has_child (GtkTreeModel * tree_model,
782 GtkTreeIter * iter)
783{
784 FileBrowserNode *node;
785 PlumaFileBrowserStore *model;
786
787 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_203
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_203 = 1; else _g_boolean_var_203 =
0; _g_boolean_var_203; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
788 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_203
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_203 = 1; else _g_boolean_var_203 =
0; _g_boolean_var_203; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
789 g_return_val_if_fail (iter == NULLdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_204
; if (iter == ((void*)0) || iter->user_data != ((void*)0))
_g_boolean_var_204 = 1; else _g_boolean_var_204 = 0; _g_boolean_var_204
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "iter == NULL || iter->user_data != NULL"
); return ((0)); } } while (0)
790 || iter->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_204
; if (iter == ((void*)0) || iter->user_data != ((void*)0))
_g_boolean_var_204 = 1; else _g_boolean_var_204 = 0; _g_boolean_var_204
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "iter == NULL || iter->user_data != NULL"
); return ((0)); } } while (0)
;
791
792 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
793
794 if (iter == NULL((void*)0))
795 node = model->priv->virtual_root;
796 else
797 node = (FileBrowserNode *) (iter->user_data);
798
799 return filter_tree_model_iter_has_child_real (model, node);
800}
801
802static gint
803pluma_file_browser_store_iter_n_children (GtkTreeModel * tree_model,
804 GtkTreeIter * iter)
805{
806 FileBrowserNode *node;
807 PlumaFileBrowserStore *model;
808 GSList *item;
809 gint num = 0;
810
811 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_205
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_205 = 1; else _g_boolean_var_205 =
0; _g_boolean_var_205; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
812 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_205
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_205 = 1; else _g_boolean_var_205 =
0; _g_boolean_var_205; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
813 g_return_val_if_fail (iter == NULLdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_206
; if (iter == ((void*)0) || iter->user_data != ((void*)0))
_g_boolean_var_206 = 1; else _g_boolean_var_206 = 0; _g_boolean_var_206
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "iter == NULL || iter->user_data != NULL"
); return ((0)); } } while (0)
814 || iter->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_206
; if (iter == ((void*)0) || iter->user_data != ((void*)0))
_g_boolean_var_206 = 1; else _g_boolean_var_206 = 0; _g_boolean_var_206
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "iter == NULL || iter->user_data != NULL"
); return ((0)); } } while (0)
;
815
816 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
817
818 if (iter == NULL((void*)0))
819 node = model->priv->virtual_root;
820 else
821 node = (FileBrowserNode *) (iter->user_data);
822
823 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
824 return 0;
825
826 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item; item = item->next)
827 if (model_node_inserted (model, (FileBrowserNode *) (item->data)))
828 ++num;
829
830 return num;
831}
832
833static gboolean
834pluma_file_browser_store_iter_nth_child (GtkTreeModel * tree_model,
835 GtkTreeIter * iter,
836 GtkTreeIter * parent, gint n)
837{
838 FileBrowserNode *node;
839 PlumaFileBrowserStore *model;
840 GSList *item;
841 gint num = 0;
842
843 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_207
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_207 = 1; else _g_boolean_var_207 =
0; _g_boolean_var_207; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
844 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_207
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_207 = 1; else _g_boolean_var_207 =
0; _g_boolean_var_207; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
845 g_return_val_if_fail (parent == NULLdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_208
; if (parent == ((void*)0) || parent->user_data != ((void*
)0)) _g_boolean_var_208 = 1; else _g_boolean_var_208 = 0; _g_boolean_var_208
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "parent == NULL || parent->user_data != NULL"
); return ((0)); } } while (0)
846 || parent->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_208
; if (parent == ((void*)0) || parent->user_data != ((void*
)0)) _g_boolean_var_208 = 1; else _g_boolean_var_208 = 0; _g_boolean_var_208
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "parent == NULL || parent->user_data != NULL"
); return ((0)); } } while (0)
;
847
848 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
849
850 if (parent == NULL((void*)0))
851 node = model->priv->virtual_root;
852 else
853 node = (FileBrowserNode *) (parent->user_data);
854
855 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
856 return FALSE(0);
857
858 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item;
859 item = item->next) {
860 if (model_node_inserted (model, (FileBrowserNode *) (item->data))) {
861 if (num == n) {
862 iter->user_data = item->data;
863 return TRUE(!(0));
864 }
865
866 ++num;
867 }
868 }
869
870 return FALSE(0);
871}
872
873static gboolean
874pluma_file_browser_store_iter_parent (GtkTreeModel * tree_model,
875 GtkTreeIter * iter,
876 GtkTreeIter * child)
877{
878 FileBrowserNode *node;
879 PlumaFileBrowserStore *model;
880
881 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_209
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_209 = 1; else _g_boolean_var_209 =
0; _g_boolean_var_209; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
882 g_return_val_if_fail (child != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_210
; if (child != ((void*)0)) _g_boolean_var_210 = 1; else _g_boolean_var_210
= 0; _g_boolean_var_210; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "child != NULL");
return ((0)); } } while (0)
;
883 g_return_val_if_fail (child->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_211
; if (child->user_data != ((void*)0)) _g_boolean_var_211 =
1; else _g_boolean_var_211 = 0; _g_boolean_var_211; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "child->user_data != NULL"); return ((0));
} } while (0)
;
884
885 node = (FileBrowserNode *) (child->user_data);
886 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
887
888 if (!node_in_tree (model, node))
889 return FALSE(0);
890
891 if (node->parent == NULL((void*)0))
892 return FALSE(0);
893
894 iter->user_data = node->parent;
895 return TRUE(!(0));
896}
897
898static void
899pluma_file_browser_store_row_inserted (GtkTreeModel * tree_model,
900 GtkTreePath * path,
901 GtkTreeIter * iter)
902{
903 FileBrowserNode * node = (FileBrowserNode *)(iter->user_data);
904
905 node->inserted = TRUE(!(0));
906}
907
908static gboolean
909pluma_file_browser_store_row_draggable (GtkTreeDragSource * drag_source,
910 GtkTreePath * path)
911{
912 GtkTreeIter iter;
913 PlumaFileBrowserStoreFlag flags;
914
915 if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source)((((GtkTreeModel*) (void *) ((drag_source))))),
916 &iter, path))
917 {
918 return FALSE(0);
919 }
920
921 gtk_tree_model_get (GTK_TREE_MODEL (drag_source)((((GtkTreeModel*) (void *) ((drag_source))))), &iter,
922 PLUMA_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
923 -1);
924
925 return !FILE_IS_DUMMY(flags)(flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY);
926}
927
928static gboolean
929pluma_file_browser_store_drag_data_delete (GtkTreeDragSource * drag_source,
930 GtkTreePath * path)
931{
932 return FALSE(0);
933}
934
935static gboolean
936pluma_file_browser_store_drag_data_get (GtkTreeDragSource * drag_source,
937 GtkTreePath * path,
938 GtkSelectionData * selection_data)
939{
940 GtkTreeIter iter;
941 gchar *uri;
942 gchar *uris[2] = {0, };
943 gboolean ret;
944
945 if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source)((((GtkTreeModel*) (void *) ((drag_source))))),
946 &iter, path))
947 {
948 return FALSE(0);
949 }
950
951 gtk_tree_model_get (GTK_TREE_MODEL (drag_source)((((GtkTreeModel*) (void *) ((drag_source))))), &iter,
952 PLUMA_FILE_BROWSER_STORE_COLUMN_URI, &uri,
953 -1);
954
955 g_assert (uri)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_212
; if (uri) _g_boolean_var_212 = 1; else _g_boolean_var_212 = 0
; _g_boolean_var_212; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "pluma-file-browser-store.c", 955, ((const char
*) (__func__)), "uri"); } while (0)
;
956
957 uris[0] = uri;
958 ret = gtk_selection_data_set_uris (selection_data, uris);
959
960 g_free (uri);
961
962 return ret;
963}
964
965#define FILTER_HIDDEN(mode)(mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_HIDDEN) (mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_HIDDEN)
966#define FILTER_BINARY(mode)(mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_BINARY) (mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_BINARY)
967
968/* Private */
969static void
970model_begin_loading (PlumaFileBrowserStore * model, FileBrowserNode * node)
971{
972 GtkTreeIter iter;
973
974 iter.user_data = node;
975 g_signal_emit (model, model_signals[BEGIN_LOADING], 0, &iter);
976}
977
978static void
979model_end_loading (PlumaFileBrowserStore * model, FileBrowserNode * node)
980{
981 GtkTreeIter iter;
982
983 iter.user_data = node;
984 g_signal_emit (model, model_signals[END_LOADING], 0, &iter);
985}
986
987static void
988model_node_update_visibility (PlumaFileBrowserStore * model,
989 FileBrowserNode * node)
990{
991 GtkTreeIter iter;
992
993 node->flags &= ~PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED;
994
995 if (FILTER_HIDDEN (model->priv->filter_mode)(model->priv->filter_mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_HIDDEN
)
&&
996 NODE_IS_HIDDEN (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
))
)
997 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED;
998 else if (FILTER_BINARY (model->priv->filter_mode)(model->priv->filter_mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_BINARY
)
&&
999 (!NODE_IS_TEXT (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_TEXT
))
&& !NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
))
1000 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED;
1001 else if (model->priv->filter_func) {
1002 iter.user_data = node;
1003
1004 if (!model->priv->
1005 filter_func (model, &iter,
1006 model->priv->filter_user_data))
1007 node->flags |=
1008 PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED;
1009 }
1010}
1011
1012static gint
1013collate_nodes (FileBrowserNode * node1, FileBrowserNode * node2)
1014{
1015 if (node1->name == NULL((void*)0))
1016 return -1;
1017 else if (node2->name == NULL((void*)0))
1018 return 1;
1019 else {
1020 gchar *k1, *k2;
1021 gint result;
1022
1023 k1 = g_utf8_collate_key_for_filename (node1->name, -1);
1024 k2 = g_utf8_collate_key_for_filename (node2->name, -1);
1025
1026 result = strcmp (k1, k2);
1027
1028 g_free (k1);
1029 g_free (k2);
1030
1031 return result;
1032 }
1033}
1034
1035static gint
1036model_sort_default (FileBrowserNode * node1, FileBrowserNode * node2)
1037{
1038 gint f1;
1039 gint f2;
1040
1041 f1 = NODE_IS_DUMMY (node1)(((node1)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
;
1042 f2 = NODE_IS_DUMMY (node2)(((node2)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
;
1043
1044 if (f1 && f2)
1045 {
1046 return 0;
1047 }
1048 else if (f1 || f2)
1049 {
1050 return f1 ? -1 : 1;
1051 }
1052
1053 f1 = NODE_IS_DIR (node1)(((node1)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
;
1054 f2 = NODE_IS_DIR (node2)(((node2)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
;
1055
1056 if (f1 != f2)
1057 {
1058 return f1 ? -1 : 1;
1059 }
1060
1061 f1 = NODE_IS_HIDDEN (node1)(((node1)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
))
;
1062 f2 = NODE_IS_HIDDEN (node2)(((node2)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
))
;
1063
1064 if (f1 != f2)
1065 {
1066 return f2 ? -1 : 1;
1067 }
1068
1069 return collate_nodes (node1, node2);
1070}
1071
1072static void
1073model_resort_node (PlumaFileBrowserStore * model, FileBrowserNode * node)
1074{
1075 FileBrowserNodeDir *dir;
1076 GSList *item;
1077 FileBrowserNode *child;
1078 gint pos = 0;
1079 GtkTreeIter iter;
1080 GtkTreePath *path;
1081 gint *neworder;
1082
1083 dir = FILE_BROWSER_NODE_DIR (node->parent)((FileBrowserNodeDir *)(node->parent));
1084
1085 if (!model_node_visibility (model, node->parent)) {
26
Taking false branch
1086 /* Just sort the children of the parent */
1087 dir->children = g_slist_sort (dir->children,
1088 (GCompareFunc) (model->priv->
1089 sort_func));
1090 } else {
1091 /* Store current positions */
1092 for (item = dir->children; item; item = item->next) {
27
Loop condition is false. Execution continues on line 1099
1093 child = (FileBrowserNode *) (item->data);
1094
1095 if (model_node_visibility (model, child))
1096 child->pos = pos++;
1097 }
1098
1099 dir->children = g_slist_sort (dir->children,
1100 (GCompareFunc) (model->priv->
1101 sort_func));
1102 neworder = g_new (gint, pos)(gint *) (__extension__ ({ gsize __n = (gsize) (pos); gsize __s
= sizeof (gint); gpointer __p; if (__s == 1) __p = g_malloc (
__n); else if (__builtin_constant_p (__n) && (__s == 0
|| __n <= (9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc
(__n * __s); else __p = g_malloc_n (__n, __s); __p; }))
;
28
Taking false branch
1103 pos = 0;
1104
1105 /* Store the new positions */
1106 for (item = dir->children; item; item = item->next) {
29
Loop condition is true. Entering loop body
1107 child = (FileBrowserNode *) (item->data);
1108
1109 if (model_node_visibility (model, child))
30
Taking true branch
1110 neworder[pos++] = child->pos;
31
Out of bound memory access (access exceeds upper limit of memory block)
1111 }
1112
1113 iter.user_data = node->parent;
1114 path =
1115 pluma_file_browser_store_get_path_real (model,
1116 node->parent);
1117
1118 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (model)((((GtkTreeModel*) (void *) ((model))))),
1119 path, &iter, neworder);
1120
1121 g_free (neworder);
1122 gtk_tree_path_free (path);
1123 }
1124}
1125
1126static void
1127row_changed (PlumaFileBrowserStore * model,
1128 GtkTreePath ** path,
1129 GtkTreeIter * iter)
1130{
1131 GtkTreeRowReference *ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (model)((((GtkTreeModel*) (void *) ((model))))), *path);
1132
1133 /* Insert a copy of the actual path here because the row-inserted
1134 signal may alter the path */
1135 gtk_tree_model_row_changed (GTK_TREE_MODEL(model)((((GtkTreeModel*) (void *) ((model))))), *path, iter);
1136 gtk_tree_path_free (*path);
1137
1138 *path = gtk_tree_row_reference_get_path (ref);
1139 gtk_tree_row_reference_free (ref);
1140}
1141
1142static void
1143row_inserted (PlumaFileBrowserStore * model,
1144 GtkTreePath ** path,
1145 GtkTreeIter * iter)
1146{
1147 /* This function creates a row reference for the path because it's
1148 uncertain what might change the actual model/view when we insert
1149 a node, maybe another directory load is triggered for example.
1150 Because functions that use this function rely on the notion that
1151 the path remains pointed towards the inserted node, we use the
1152 reference to keep track. */
1153 GtkTreeRowReference *ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (model)((((GtkTreeModel*) (void *) ((model))))), *path);
1154 GtkTreePath * copy = gtk_tree_path_copy (*path);
1155
1156 gtk_tree_model_row_inserted (GTK_TREE_MODEL(model)((((GtkTreeModel*) (void *) ((model))))), copy, iter);
1157 gtk_tree_path_free (copy);
1158
1159 if (ref)
1160 {
1161 gtk_tree_path_free (*path);
1162
1163 /* To restore the path, we get the path from the reference. But, since
1164 we inserted a row, the path will be one index further than the
1165 actual path of our node. We therefore call gtk_tree_path_prev */
1166 *path = gtk_tree_row_reference_get_path (ref);
1167 gtk_tree_path_prev (*path);
1168 }
1169
1170 gtk_tree_row_reference_free (ref);
1171}
1172
1173static void
1174row_deleted (PlumaFileBrowserStore * model,
1175 const GtkTreePath * path)
1176{
1177 GtkTreePath *copy = gtk_tree_path_copy (path);
1178
1179 /* Delete a copy of the actual path here because the row-deleted
1180 signal may alter the path */
1181 gtk_tree_model_row_deleted (GTK_TREE_MODEL(model)((((GtkTreeModel*) (void *) ((model))))), copy);
1182 gtk_tree_path_free (copy);
1183}
1184
1185static void
1186model_refilter_node (PlumaFileBrowserStore * model,
1187 FileBrowserNode * node,
1188 GtkTreePath ** path)
1189{
1190 gboolean old_visible;
1191 gboolean new_visible;
1192 FileBrowserNodeDir *dir;
1193 GSList *item;
1194 GtkTreeIter iter;
1195 GtkTreePath *tmppath = NULL((void*)0);
1196 gboolean in_tree;
1197
1198 if (node == NULL((void*)0))
1199 return;
1200
1201 old_visible = model_node_visibility (model, node);
1202 model_node_update_visibility (model, node);
1203
1204 in_tree = node_in_tree (model, node);
1205
1206 if (path == NULL((void*)0))
1207 {
1208 if (in_tree)
1209 tmppath = pluma_file_browser_store_get_path_real (model,
1210 node);
1211 else
1212 tmppath = gtk_tree_path_new_first ();
1213
1214 path = &tmppath;
1215 }
1216
1217 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
1218 if (in_tree)
1219 gtk_tree_path_down (*path);
1220
1221 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
1222
1223 for (item = dir->children; item; item = item->next) {
1224 model_refilter_node (model,
1225 (FileBrowserNode *) (item->data),
1226 path);
1227 }
1228
1229 if (in_tree)
1230 gtk_tree_path_up (*path);
1231 }
1232
1233 if (in_tree) {
1234 new_visible = model_node_visibility (model, node);
1235
1236 if (old_visible != new_visible) {
1237 if (old_visible) {
1238 node->inserted = FALSE(0);
1239 row_deleted (model, *path);
1240 } else {
1241 iter.user_data = node;
1242 row_inserted (model, path, &iter);
1243 gtk_tree_path_next (*path);
1244 }
1245 } else if (old_visible) {
1246 gtk_tree_path_next (*path);
1247 }
1248 }
1249
1250 model_check_dummy (model, node);
1251
1252 if (tmppath)
1253 gtk_tree_path_free (tmppath);
1254}
1255
1256static void
1257model_refilter (PlumaFileBrowserStore * model)
1258{
1259 model_refilter_node (model, model->priv->root, NULL((void*)0));
1260}
1261
1262static void
1263file_browser_node_set_name (FileBrowserNode * node)
1264{
1265 g_free (node->name);
1266
1267 if (node->file) {
1268 node->name = pluma_file_browser_utils_file_basename (node->file);
1269 } else {
1270 node->name = NULL((void*)0);
1271 }
1272}
1273
1274static void
1275file_browser_node_init (FileBrowserNode * node, GFile * file,
1276 FileBrowserNode * parent)
1277{
1278 if (file != NULL((void*)0)) {
1279 node->file = g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
1280 file_browser_node_set_name (node);
1281 }
1282
1283 node->parent = parent;
1284}
1285
1286static FileBrowserNode *
1287file_browser_node_new (GFile * file, FileBrowserNode * parent)
1288{
1289 FileBrowserNode *node = g_slice_new0 (FileBrowserNode)(FileBrowserNode *) (__extension__ ({ gsize __s = sizeof (FileBrowserNode
); gpointer __p; __p = g_slice_alloc (__s); memset (__p, 0, __s
); __p; }))
;
1290
1291 file_browser_node_init (node, file, parent);
1292 return node;
1293}
1294
1295static FileBrowserNode *
1296file_browser_node_dir_new (PlumaFileBrowserStore * model,
1297 GFile * file, FileBrowserNode * parent)
1298{
1299 FileBrowserNode *node =
1300 (FileBrowserNode *) g_slice_new0 (FileBrowserNodeDir)(FileBrowserNodeDir *) (__extension__ ({ gsize __s = sizeof (
FileBrowserNodeDir); gpointer __p; __p = g_slice_alloc (__s);
memset (__p, 0, __s); __p; }))
;
1301
1302 file_browser_node_init (node, file, parent);
1303
1304 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY;
1305
1306 FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->model = model;
1307
1308 return node;
1309}
1310
1311static void
1312file_browser_node_free_children (PlumaFileBrowserStore * model,
1313 FileBrowserNode * node)
1314{
1315 GSList *item;
1316
1317 if (node == NULL((void*)0))
1318 return;
1319
1320 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
1321 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item;
1322 item = item->next)
1323 file_browser_node_free (model,
1324 (FileBrowserNode *) (item->
1325 data));
1326
1327 g_slist_free (FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children);
1328 FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children = NULL((void*)0);
1329
1330 /* This node is no longer loaded */
1331 node->flags &= ~PLUMA_FILE_BROWSER_STORE_FLAG_LOADED;
1332 }
1333}
1334
1335static void
1336file_browser_node_free (PlumaFileBrowserStore * model,
1337 FileBrowserNode * node)
1338{
1339 gchar *uri;
1340
1341 if (node == NULL((void*)0))
1342 return;
1343
1344 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
1345 {
1346 FileBrowserNodeDir *dir;
1347
1348 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
1349
1350 if (dir->cancellable) {
1351 g_cancellable_cancel (dir->cancellable);
1352 g_object_unref (dir->cancellable);
1353
1354 model_end_loading (model, node);
1355 }
1356
1357 file_browser_node_free_children (model, node);
1358
1359 if (dir->monitor) {
1360 g_file_monitor_cancel (dir->monitor);
1361 g_object_unref (dir->monitor);
1362 }
1363 }
1364
1365 if (node->file)
1366 {
1367 uri = g_file_get_uri (node->file);
1368 g_signal_emit (model, model_signals[UNLOAD], 0, uri);
1369
1370 g_free (uri);
1371 g_object_unref (node->file);
1372 }
1373
1374 if (node->icon)
1375 g_object_unref (node->icon);
1376
1377 if (node->emblem)
1378 g_object_unref (node->emblem);
1379
1380 g_free (node->name);
1381
1382 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
1383 g_slice_free (FileBrowserNodeDir, (FileBrowserNodeDir *)node)do { if (1) g_slice_free1 (sizeof (FileBrowserNodeDir), ((FileBrowserNodeDir
*)node)); else (void) ((FileBrowserNodeDir*) 0 == ((FileBrowserNodeDir
*)node)); } while (0)
;
1384 else
1385 g_slice_free (FileBrowserNode, (FileBrowserNode *)node)do { if (1) g_slice_free1 (sizeof (FileBrowserNode), ((FileBrowserNode
*)node)); else (void) ((FileBrowserNode*) 0 == ((FileBrowserNode
*)node)); } while (0)
;
1386}
1387
1388/**
1389 * model_remove_node_children:
1390 * @model: the #PlumaFileBrowserStore
1391 * @node: the FileBrowserNode to remove
1392 * @path: the path of the node, or NULL to let the path be calculated
1393 * @free_nodes: whether to also remove the nodes from memory
1394 *
1395 * Removes all the children of node from the model. This function is used
1396 * to remove the child nodes from the _model_. Don't use it to just free
1397 * a node.
1398 **/
1399static void
1400model_remove_node_children (PlumaFileBrowserStore * model,
1401 FileBrowserNode * node,
1402 GtkTreePath * path,
1403 gboolean free_nodes)
1404{
1405 FileBrowserNodeDir *dir;
1406 GtkTreePath *path_child;
1407 GSList *list;
1408 GSList *item;
1409
1410 if (node == NULL((void*)0) || !NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
1411 return;
1412
1413 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
1414
1415 if (dir->children == NULL((void*)0))
1416 return;
1417
1418 if (!model_node_visibility (model, node)) {
1419 // Node is invisible and therefore the children can just
1420 // be freed
1421 if (free_nodes)
1422 file_browser_node_free_children (model, node);
1423
1424 return;
1425 }
1426
1427 if (path == NULL((void*)0))
1428 path_child =
1429 pluma_file_browser_store_get_path_real (model, node);
1430 else
1431 path_child = gtk_tree_path_copy (path);
1432
1433 gtk_tree_path_down (path_child);
1434
1435 list = g_slist_copy (dir->children);
1436
1437 for (item = list; item; item = item->next) {
1438 model_remove_node (model, (FileBrowserNode *) (item->data),
1439 path_child, free_nodes);
1440 }
1441
1442 g_slist_free (list);
1443 gtk_tree_path_free (path_child);
1444}
1445
1446/**
1447 * model_remove_node:
1448 * @model: the #PlumaFileBrowserStore
1449 * @node: the FileBrowserNode to remove
1450 * @path: the path to use to remove this node, or NULL to use the path
1451 * calculated from the node itself
1452 * @free_nodes: whether to also remove the nodes from memory
1453 *
1454 * Removes this node and all its children from the model. This function is used
1455 * to remove the node from the _model_. Don't use it to just free
1456 * a node.
1457 **/
1458static void
1459model_remove_node (PlumaFileBrowserStore * model,
1460 FileBrowserNode * node,
1461 GtkTreePath * path,
1462 gboolean free_nodes)
1463{
1464 gboolean free_path = FALSE(0);
1465 FileBrowserNode *parent;
1466
1467 if (path == NULL((void*)0)) {
1468 path =
1469 pluma_file_browser_store_get_path_real (model, node);
1470 free_path = TRUE(!(0));
1471 }
1472
1473 model_remove_node_children (model, node, path, free_nodes);
1474
1475 /* Only delete if the node is visible in the tree (but only when it's
1476 not the virtual root) */
1477 if (model_node_visibility (model, node) && node != model->priv->virtual_root)
1478 {
1479 node->inserted = FALSE(0);
1480 row_deleted (model, path);
1481 }
1482
1483 if (free_path)
1484 gtk_tree_path_free (path);
1485
1486 parent = node->parent;
1487
1488 if (free_nodes) {
1489 /* Remove the node from the parents children list */
1490 if (parent)
1491 FILE_BROWSER_NODE_DIR (node->parent)((FileBrowserNodeDir *)(node->parent))->children =
1492 g_slist_remove (FILE_BROWSER_NODE_DIR((FileBrowserNodeDir *)(node->parent))
1493 (node->parent)((FileBrowserNodeDir *)(node->parent))->children,
1494 node);
1495 }
1496
1497 /* If this is the virtual root, than set the parent as the virtual root */
1498 if (node == model->priv->virtual_root)
1499 set_virtual_root_from_node (model, parent);
1500 else if (parent && model_node_visibility (model, parent) && !(free_nodes && NODE_IS_DUMMY(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
))
1501 model_check_dummy (model, parent);
1502
1503 /* Now free the node if necessary */
1504 if (free_nodes)
1505 file_browser_node_free (model, node);
1506}
1507
1508/**
1509 * model_clear:
1510 * @model: the #PlumaFileBrowserStore
1511 * @free_nodes: whether to also remove the nodes from memory
1512 *
1513 * Removes all nodes from the model. This function is used
1514 * to remove all the nodes from the _model_. Don't use it to just free the
1515 * nodes in the model.
1516 **/
1517static void
1518model_clear (PlumaFileBrowserStore * model, gboolean free_nodes)
1519{
1520 GtkTreePath *path;
1521 FileBrowserNodeDir *dir;
1522 FileBrowserNode *dummy;
1523
1524 path = gtk_tree_path_new ();
1525 model_remove_node_children (model, model->priv->virtual_root, path,
1526 free_nodes);
1527 gtk_tree_path_free (path);
1528
1529 /* Remove the dummy if there is one */
1530 if (model->priv->virtual_root) {
1531 dir = FILE_BROWSER_NODE_DIR (model->priv->virtual_root)((FileBrowserNodeDir *)(model->priv->virtual_root));
1532
1533 if (dir->children != NULL((void*)0)) {
1534 dummy = (FileBrowserNode *) (dir->children->data);
1535
1536 if (NODE_IS_DUMMY (dummy)(((dummy)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
1537 && model_node_visibility (model, dummy)) {
1538 path = gtk_tree_path_new_first ();
1539
1540 dummy->inserted = FALSE(0);
1541 row_deleted (model, path);
1542 gtk_tree_path_free (path);
1543 }
1544 }
1545 }
1546}
1547
1548static void
1549file_browser_node_unload (PlumaFileBrowserStore * model,
1550 FileBrowserNode * node, gboolean remove_children)
1551{
1552 FileBrowserNodeDir *dir;
1553
1554 if (node == NULL((void*)0))
1555 return;
1556
1557 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
|| !NODE_LOADED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
)
1558 return;
1559
1560 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
1561
1562 if (remove_children)
1563 model_remove_node_children (model, node, NULL((void*)0), TRUE(!(0)));
1564
1565 if (dir->cancellable) {
1566 g_cancellable_cancel (dir->cancellable);
1567 g_object_unref (dir->cancellable);
1568
1569 model_end_loading (model, node);
1570 dir->cancellable = NULL((void*)0);
1571 }
1572
1573 if (dir->monitor) {
1574 g_file_monitor_cancel (dir->monitor);
1575 g_object_unref (dir->monitor);
1576
1577 dir->monitor = NULL((void*)0);
1578 }
1579
1580 node->flags &= ~PLUMA_FILE_BROWSER_STORE_FLAG_LOADED;
1581}
1582
1583static void
1584model_recomposite_icon_real (PlumaFileBrowserStore * tree_model,
1585 FileBrowserNode * node,
1586 GFileInfo * info)
1587{
1588 GdkPixbuf *icon;
1589
1590 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_213
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_213 = 1; else _g_boolean_var_213 =
0; _g_boolean_var_213; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return; } } while (0)
;
1591 g_return_if_fail (node != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_214
; if (node != ((void*)0)) _g_boolean_var_214 = 1; else _g_boolean_var_214
= 0; _g_boolean_var_214; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "node != NULL"); return
; } } while (0)
;
1592
1593 if (node->file == NULL((void*)0))
1594 return;
1595
1596 if (info) {
1597 GIcon *gicon = g_file_info_get_icon (info);
1598 if (gicon != NULL((void*)0))
1599 icon = pluma_file_browser_utils_pixbuf_from_icon (gicon, GTK_ICON_SIZE_MENU);
1600 else
1601 icon = NULL((void*)0);
1602 } else {
1603 icon = pluma_file_browser_utils_pixbuf_from_file (node->file, GTK_ICON_SIZE_MENU);
1604 }
1605
1606 if (node->icon)
1607 g_object_unref (node->icon);
1608
1609 if (node->emblem) {
1610 gint icon_size;
1611
1612 gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL((void*)0), &icon_size);
1613
1614 if (icon == NULL((void*)0)) {
1615 node->icon =
1616 gdk_pixbuf_new (gdk_pixbuf_get_colorspace (node->emblem),
1617 gdk_pixbuf_get_has_alpha (node->emblem),
1618 gdk_pixbuf_get_bits_per_sample (node->emblem),
1619 icon_size,
1620 icon_size);
1621 } else {
1622 node->icon = gdk_pixbuf_copy (icon);
1623 g_object_unref (icon);
1624 }
1625
1626 gdk_pixbuf_composite (node->emblem, node->icon,
1627 icon_size - 10, icon_size - 10, 10,
1628 10, icon_size - 10, icon_size - 10,
1629 1, 1, GDK_INTERP_NEAREST, 255);
1630 } else {
1631 node->icon = icon;
1632 }
1633}
1634
1635static void
1636model_recomposite_icon (PlumaFileBrowserStore * tree_model,
1637 GtkTreeIter * iter)
1638{
1639 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_215
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_215 = 1; else _g_boolean_var_215 =
0; _g_boolean_var_215; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return; } } while (0)
;
1640 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_216
; if (iter != ((void*)0)) _g_boolean_var_216 = 1; else _g_boolean_var_216
= 0; _g_boolean_var_216; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
1641 g_return_if_fail (iter->user_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_217
; if (iter->user_data != ((void*)0)) _g_boolean_var_217 = 1
; else _g_boolean_var_217 = 0; _g_boolean_var_217; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return; } } while
(0)
;
1642
1643 model_recomposite_icon_real (tree_model,
1644 (FileBrowserNode *) (iter->user_data),
1645 NULL((void*)0));
1646}
1647
1648static FileBrowserNode *
1649model_create_dummy_node (PlumaFileBrowserStore * model,
1650 FileBrowserNode * parent)
1651{
1652 FileBrowserNode *dummy;
1653
1654 dummy = file_browser_node_new (NULL((void*)0), parent);
1655 dummy->name = g_strdup (_("(Empty)"))g_strdup_inline (((char *) g_dgettext ("pluma", "(Empty)")));
1656
1657 dummy->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY;
1658 dummy->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1659
1660 return dummy;
1661}
1662
1663static FileBrowserNode *
1664model_add_dummy_node (PlumaFileBrowserStore * model,
1665 FileBrowserNode * parent)
1666{
1667 FileBrowserNode *dummy;
1668
1669 dummy = model_create_dummy_node (model, parent);
1670
1671 if (model_node_visibility (model, parent))
1672 dummy->flags &= ~PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1673
1674 model_add_node (model, dummy, parent);
1675
1676 return dummy;
1677}
1678
1679static void
1680model_check_dummy (PlumaFileBrowserStore * model, FileBrowserNode * node)
1681{
1682 // Hide the dummy child if needed
1683 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
1684 FileBrowserNode *dummy;
1685 GtkTreeIter iter;
1686 GtkTreePath *path;
1687 guint flags;
1688 FileBrowserNodeDir *dir;
1689
1690 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
1691
1692 if (dir->children == NULL((void*)0)) {
1693 model_add_dummy_node (model, node);
1694 return;
1695 }
1696
1697 dummy = (FileBrowserNode *) (dir->children->data);
1698
1699 if (!NODE_IS_DUMMY (dummy)(((dummy)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
) {
1700 dummy = model_create_dummy_node (model, node);
1701 dir->children = g_slist_prepend (dir->children, dummy);
1702 }
1703
1704 if (!model_node_visibility (model, node)) {
1705 dummy->flags |=
1706 PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1707 return;
1708 }
1709
1710 /* Temporarily set the node to invisible to check
1711 * for real children */
1712 flags = dummy->flags;
1713 dummy->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1714
1715 if (!filter_tree_model_iter_has_child_real (model, node)) {
1716 dummy->flags &=
1717 ~PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1718
1719 if (FILE_IS_HIDDEN (flags)(flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN)) {
1720 // Was hidden, needs to be inserted
1721 iter.user_data = dummy;
1722 path =
1723 pluma_file_browser_store_get_path_real
1724 (model, dummy);
1725
1726 row_inserted (model, &path, &iter);
1727 gtk_tree_path_free (path);
1728 }
1729 } else {
1730 if (!FILE_IS_HIDDEN (flags)(flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN)) {
1731 // Was shown, needs to be removed
1732
1733 // To get the path we need to set it to visible temporarily
1734 dummy->flags &=
1735 ~PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1736 path =
1737 pluma_file_browser_store_get_path_real
1738 (model, dummy);
1739 dummy->flags |=
1740 PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1741
1742 dummy->inserted = FALSE(0);
1743 row_deleted (model, path);
1744 gtk_tree_path_free (path);
1745 }
1746 }
1747 }
1748}
1749
1750static void
1751insert_node_sorted (PlumaFileBrowserStore * model,
1752 FileBrowserNode * child,
1753 FileBrowserNode * parent)
1754{
1755 FileBrowserNodeDir *dir;
1756
1757 dir = FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent));
1758
1759 if (model->priv->sort_func == NULL((void*)0)) {
1760 dir->children = g_slist_append (dir->children, child);
1761 } else {
1762 dir->children =
1763 g_slist_insert_sorted (dir->children, child,
1764 (GCompareFunc) (model->priv->
1765 sort_func));
1766 }
1767}
1768
1769static void
1770model_add_node (PlumaFileBrowserStore * model, FileBrowserNode * child,
1771 FileBrowserNode * parent)
1772{
1773 /* Add child to parents children */
1774 insert_node_sorted (model, child, parent);
1775
1776 if (model_node_visibility (model, parent) &&
1777 model_node_visibility (model, child)) {
1778 GtkTreeIter iter;
1779 GtkTreePath *path;
1780
1781 iter.user_data = child;
1782 path = pluma_file_browser_store_get_path_real (model, child);
1783
1784 /* Emit row inserted */
1785 row_inserted (model, &path, &iter);
1786 gtk_tree_path_free (path);
1787 }
1788
1789 model_check_dummy (model, parent);
1790 model_check_dummy (model, child);
1791}
1792
1793static void
1794model_add_nodes_batch (PlumaFileBrowserStore * model,
1795 GSList * children,
1796 FileBrowserNode * parent)
1797{
1798 GSList *sorted_children;
1799 GSList *child;
1800 GSList *prev;
1801 GSList *l;
1802 FileBrowserNodeDir *dir;
1803
1804 dir = FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent));
1805
1806 sorted_children = g_slist_sort (children, (GCompareFunc) model->priv->sort_func);
1807
1808 child = sorted_children;
1809 l = dir->children;
1810 prev = NULL((void*)0);
1811
1812 model_check_dummy (model, parent);
1813
1814 while (child) {
1815 FileBrowserNode *node = child->data;
1816 GtkTreeIter iter;
1817 GtkTreePath *path;
1818
1819 /* reached the end of the first list, just append the second */
1820 if (l == NULL((void*)0)) {
1821
1822 dir->children = g_slist_concat (dir->children, child);
1823
1824 for (l = child; l; l = l->next) {
1825 if (model_node_visibility (model, parent) &&
1826 model_node_visibility (model, l->data)) {
1827 iter.user_data = l->data;
1828 path = pluma_file_browser_store_get_path_real (model, l->data);
1829
1830 // Emit row inserted
1831 row_inserted (model, &path, &iter);
1832 gtk_tree_path_free (path);
1833 }
1834
1835 model_check_dummy (model, l->data);
1836 }
1837
1838 break;
1839 }
1840
1841 if (model->priv->sort_func (l->data, node) > 0) {
1842 GSList *next_child;
1843
1844 if (prev == NULL((void*)0)) {
1845 /* prepend to the list */
1846 dir->children = g_slist_prepend (dir->children, child);
1847 } else {
1848 prev->next = child;
1849 }
1850
1851 next_child = child->next;
1852 prev = child;
1853 child->next = l;
1854 child = next_child;
1855
1856 if (model_node_visibility (model, parent) &&
1857 model_node_visibility (model, node)) {
1858 iter.user_data = node;
1859 path = pluma_file_browser_store_get_path_real (model, node);
1860
1861 // Emit row inserted
1862 row_inserted (model, &path, &iter);
1863 gtk_tree_path_free (path);
1864 }
1865
1866 model_check_dummy (model, node);
1867
1868 /* try again at the same l position with the
1869 * next child */
1870 } else {
1871
1872 /* Move to the next item in the list */
1873 prev = l;
1874 l = l->next;
1875 }
1876 }
1877}
1878
1879static gchar const *
1880backup_content_type (GFileInfo * info)
1881{
1882 gchar const * content;
1883
1884 if (!g_file_info_get_is_backup (info))
1885 return NULL((void*)0);
1886
1887 content = g_file_info_get_content_type (info);
1888
1889 if (!content || g_content_type_equals (content, "application/x-trash"))
1890 return "text/plain";
1891
1892 return content;
1893}
1894
1895static void
1896file_browser_node_set_from_info (PlumaFileBrowserStore * model,
1897 FileBrowserNode * node,
1898 GFileInfo * info,
1899 gboolean isadded)
1900{
1901 gchar const * content;
1902 gboolean free_info = FALSE(0);
1903 GtkTreePath * path;
1904 gchar * uri;
1905 GError * error = NULL((void*)0);
1906
1907 if (info == NULL((void*)0)) {
1908 info = g_file_query_info (node->file,
1909 STANDARD_ATTRIBUTE_TYPES"standard::type" "," "standard::is-hidden" "," "standard::is-backup"
"," "standard::name" "," "standard::content-type" "," "standard::icon"
,
1910 G_FILE_QUERY_INFO_NONE,
1911 NULL((void*)0),
1912 &error);
1913
1914 if (!info) {
1915 if (!(error->domain == G_IO_ERRORg_io_error_quark() && error->code == G_IO_ERROR_NOT_FOUND)) {
1916 uri = g_file_get_uri (node->file);
1917 g_warning ("Could not get info for %s: %s", uri, error->message);
1918 g_free (uri);
1919 }
1920 g_error_free (error);
1921
1922 return;
1923 }
1924
1925 free_info = TRUE(!(0));
1926 }
1927
1928 if (g_file_info_get_is_hidden (info) || g_file_info_get_is_backup (info))
1929 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1930
1931 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
1932 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY;
1933 else {
1934 if (!(content = backup_content_type (info)))
1935 content = g_file_info_get_content_type (info);
1936
1937 if (!content ||
1938 g_content_type_is_unknown (content) ||
1939 g_content_type_is_a (content, "text/plain"))
1940 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_TEXT;
1941 }
1942
1943 model_recomposite_icon_real (model, node, info);
1944
1945 if (free_info)
1946 g_object_unref (info);
1947
1948 if (isadded) {
1949 path = pluma_file_browser_store_get_path_real (model, node);
1950 model_refilter_node (model, node, &path);
1951 gtk_tree_path_free (path);
1952
1953 model_check_dummy (model, node->parent);
1954 } else {
1955 model_node_update_visibility (model, node);
1956 }
1957}
1958
1959static FileBrowserNode *
1960node_list_contains_file (GSList *children, GFile * file)
1961{
1962 GSList *item;
1963
1964 for (item = children; item; item = item->next) {
1965 FileBrowserNode *node;
1966
1967 node = (FileBrowserNode *) (item->data);
1968
1969 if (node->file != NULL((void*)0)
1970 && g_file_equal (node->file, file))
1971 return node;
1972 }
1973
1974 return NULL((void*)0);
1975}
1976
1977static FileBrowserNode *
1978model_add_node_from_file (PlumaFileBrowserStore * model,
1979 FileBrowserNode * parent,
1980 GFile * file,
1981 GFileInfo * info)
1982{
1983 FileBrowserNode *node;
1984 gboolean free_info = FALSE(0);
1985 GError * error = NULL((void*)0);
1986
1987 if ((node = node_list_contains_file (FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent))->children, file)) == NULL((void*)0)) {
1988 if (info == NULL((void*)0)) {
1989 info = g_file_query_info (file,
1990 STANDARD_ATTRIBUTE_TYPES"standard::type" "," "standard::is-hidden" "," "standard::is-backup"
"," "standard::name" "," "standard::content-type" "," "standard::icon"
,
1991 G_FILE_QUERY_INFO_NONE,
1992 NULL((void*)0),
1993 &error);
1994 free_info = TRUE(!(0));
1995 }
1996
1997 if (!info) {
1998 g_warning ("Error querying file info: %s", error->message);
1999 g_error_free (error);
2000
2001 /* FIXME: What to do now then... */
2002 node = file_browser_node_new (file, parent);
2003 } else if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
2004 node = file_browser_node_dir_new (model, file, parent);
2005 } else {
2006 node = file_browser_node_new (file, parent);
2007 }
2008
2009 file_browser_node_set_from_info (model, node, info, FALSE(0));
2010 model_add_node (model, node, parent);
2011
2012 if (info && free_info)
2013 g_object_unref (info);
2014 }
2015
2016 return node;
2017}
2018
2019/* We pass in a copy of the list of parent->children so that we do
2020 * not have to check if a file already exists among the ones we just
2021 * added */
2022static void
2023model_add_nodes_from_files (PlumaFileBrowserStore * model,
2024 FileBrowserNode * parent,
2025 GSList * original_children,
2026 GList * files)
2027{
2028 GList *item;
2029 GSList *nodes = NULL((void*)0);
2030
2031 for (item = files; item; item = item->next) {
2032 GFileInfo *info = G_FILE_INFO (item->data)((((GFileInfo*) (void *) ((item->data)))));
2033 GFileType type;
2034 gchar const * name;
2035 GFile * file;
2036 FileBrowserNode *node;
2037
2038 type = g_file_info_get_file_type (info);
2039
2040 /* Skip all non regular, non directory files */
2041 if (type != G_FILE_TYPE_REGULAR &&
2042 type != G_FILE_TYPE_DIRECTORY &&
2043 type != G_FILE_TYPE_SYMBOLIC_LINK) {
2044 g_object_unref (info);
2045 continue;
2046 }
2047
2048 name = g_file_info_get_name (info);
2049
2050 /* Skip '.' and '..' directories */
2051 if (type == G_FILE_TYPE_DIRECTORY &&
2052 (strcmp (name, ".") == 0 ||
2053 strcmp (name, "..") == 0)) {
2054 continue;
2055 }
2056
2057 file = g_file_get_child (parent->file, name);
2058
2059 if ((node = node_list_contains_file (original_children, file)) == NULL((void*)0)) {
2060
2061 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
2062 node = file_browser_node_dir_new (model, file, parent);
2063 } else {
2064 node = file_browser_node_new (file, parent);
2065 }
2066
2067 file_browser_node_set_from_info (model, node, info, FALSE(0));
2068
2069 nodes = g_slist_prepend (nodes, node);
2070 }
2071
2072 g_object_unref (file);
2073 g_object_unref (info);
2074 }
2075
2076 if (nodes)
2077 model_add_nodes_batch (model, nodes, parent);
2078}
2079
2080static FileBrowserNode *
2081model_add_node_from_dir (PlumaFileBrowserStore * model,
2082 FileBrowserNode * parent,
2083 GFile * file)
2084{
2085 FileBrowserNode *node;
2086
2087 /* Check if it already exists */
2088 if ((node = node_list_contains_file (FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent))->children, file)) == NULL((void*)0)) {
2089 node = file_browser_node_dir_new (model, file, parent);
2090 file_browser_node_set_from_info (model, node, NULL((void*)0), FALSE(0));
2091
2092 if (node->name == NULL((void*)0)) {
2093 file_browser_node_set_name (node);
2094 }
2095
2096 if (node->icon == NULL((void*)0)) {
2097 node->icon = pluma_file_browser_utils_pixbuf_from_theme ("folder", GTK_ICON_SIZE_MENU);
2098 }
2099
2100 model_add_node (model, node, parent);
2101 }
2102
2103 return node;
2104}
2105
2106static void
2107on_directory_monitor_event (GFileMonitor * monitor,
2108 GFile * file,
2109 GFile * other_file,
2110 GFileMonitorEvent event_type,
2111 FileBrowserNode * parent)
2112{
2113 FileBrowserNode *node;
2114 FileBrowserNodeDir *dir = FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent));
2115
2116 switch (event_type) {
2117 case G_FILE_MONITOR_EVENT_DELETED:
2118 node = node_list_contains_file (dir->children, file);
2119
2120 if (node != NULL((void*)0)) {
2121 model_remove_node (dir->model, node, NULL((void*)0), TRUE(!(0)));
2122 }
2123 break;
2124 case G_FILE_MONITOR_EVENT_CREATED:
2125 if (g_file_query_exists (file, NULL((void*)0))) {
2126 model_add_node_from_file (dir->model, parent, file, NULL((void*)0));
2127 }
2128
2129 break;
2130 default:
2131 break;
2132 }
2133}
2134
2135static void
2136async_node_free (AsyncNode *async)
2137{
2138 g_object_unref (async->cancellable);
2139 g_slist_free (async->original_children);
2140 g_free (async);
2141}
2142
2143static void
2144model_iterate_next_files_cb (GFileEnumerator * enumerator,
2145 GAsyncResult * result,
2146 AsyncNode * async)
2147{
2148 GList * files;
2149 GError * error = NULL((void*)0);
2150 FileBrowserNodeDir * dir = async->dir;
2151 FileBrowserNode * parent = (FileBrowserNode *)dir;
2152
2153 files = g_file_enumerator_next_files_finish (enumerator, result, &error);
2154
2155 if (files == NULL((void*)0)) {
2156 g_file_enumerator_close (enumerator, NULL((void*)0), NULL((void*)0));
2157 async_node_free (async);
2158
2159 if (!error)
2160 {
2161 /* We're done loading */
2162 g_object_unref (dir->cancellable);
2163 dir->cancellable = NULL((void*)0);
2164
2165/*
2166 * FIXME: This is temporarly, it is a bug in gio:
2167 * http://bugzilla.gnome.org/show_bug.cgi?id=565924
2168 */
2169 if (g_file_is_native (parent->file) && dir->monitor == NULL((void*)0)) {
2170 dir->monitor = g_file_monitor_directory (parent->file,
2171 G_FILE_MONITOR_NONE,
2172 NULL((void*)0),
2173 NULL((void*)0));
2174 if (dir->monitor != NULL((void*)0))
2175 {
2176 g_signal_connect (dir->monitor,g_signal_connect_data ((dir->monitor), ("changed"), (((GCallback
) (on_directory_monitor_event))), (parent), ((void*)0), (GConnectFlags
) 0)
2177 "changed",g_signal_connect_data ((dir->monitor), ("changed"), (((GCallback
) (on_directory_monitor_event))), (parent), ((void*)0), (GConnectFlags
) 0)
2178 G_CALLBACK (on_directory_monitor_event),g_signal_connect_data ((dir->monitor), ("changed"), (((GCallback
) (on_directory_monitor_event))), (parent), ((void*)0), (GConnectFlags
) 0)
2179 parent)g_signal_connect_data ((dir->monitor), ("changed"), (((GCallback
) (on_directory_monitor_event))), (parent), ((void*)0), (GConnectFlags
) 0)
;
2180 }
2181 }
2182
2183 model_check_dummy (dir->model, parent);
2184 model_end_loading (dir->model, parent);
2185 } else {
2186 /* Simply return if we were cancelled */
2187 if (error->domain == G_IO_ERRORg_io_error_quark() && error->code == G_IO_ERROR_CANCELLED)
2188 return;
2189
2190 /* Otherwise handle the error appropriately */
2191 g_signal_emit (dir->model,
2192 model_signals[ERROR],
2193 0,
2194 PLUMA_FILE_BROWSER_ERROR_LOAD_DIRECTORY,
2195 error->message);
2196
2197 file_browser_node_unload (dir->model, (FileBrowserNode *)parent, TRUE(!(0)));
2198 g_error_free (error);
2199 }
2200 } else if (g_cancellable_is_cancelled (async->cancellable)) {
2201 /* Check cancel state manually */
2202 g_file_enumerator_close (enumerator, NULL((void*)0), NULL((void*)0));
2203 async_node_free (async);
2204 } else {
2205 model_add_nodes_from_files (dir->model, parent, async->original_children, files);
2206
2207 g_list_free (files);
2208 next_files_async (enumerator, async);
2209 }
2210}
2211
2212static void
2213next_files_async (GFileEnumerator * enumerator,
2214 AsyncNode * async)
2215{
2216 g_file_enumerator_next_files_async (enumerator,
2217 DIRECTORY_LOAD_ITEMS_PER_CALLBACK100,
2218 G_PRIORITY_DEFAULT0,
2219 async->cancellable,
2220 (GAsyncReadyCallback)model_iterate_next_files_cb,
2221 async);
2222}
2223
2224static void
2225model_iterate_children_cb (GFile * file,
2226 GAsyncResult * result,
2227 AsyncNode * async)
2228{
2229 GError * error = NULL((void*)0);
2230 GFileEnumerator * enumerator;
2231
2232 if (g_cancellable_is_cancelled (async->cancellable))
2233 {
2234 async_node_free (async);
2235 return;
2236 }
2237
2238 enumerator = g_file_enumerate_children_finish (file, result, &error);
2239
2240 if (enumerator == NULL((void*)0)) {
2241 /* Simply return if we were cancelled or if the dir is not there */
2242 FileBrowserNodeDir *dir = async->dir;
2243
2244 /* Otherwise handle the error appropriately */
2245 g_signal_emit (dir->model,
2246 model_signals[ERROR],
2247 0,
2248 PLUMA_FILE_BROWSER_ERROR_LOAD_DIRECTORY,
2249 error->message);
2250
2251 file_browser_node_unload (dir->model, (FileBrowserNode *)dir, TRUE(!(0)));
2252 g_error_free (error);
2253 async_node_free (async);
2254 } else {
2255 next_files_async (enumerator, async);
2256 }
2257}
2258
2259static void
2260model_load_directory (PlumaFileBrowserStore * model,
2261 FileBrowserNode * node)
2262{
2263 FileBrowserNodeDir *dir;
2264 AsyncNode *async;
2265
2266 g_return_if_fail (NODE_IS_DIR (node))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_218
; if ((((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))) _g_boolean_var_218 = 1; else _g_boolean_var_218 = 0; _g_boolean_var_218
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "NODE_IS_DIR (node)"); return; }
} while (0)
;
2267
2268 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
2269
2270 /* Cancel a previous load */
2271 if (dir->cancellable != NULL((void*)0)) {
2272 file_browser_node_unload (dir->model, node, TRUE(!(0)));
2273 }
2274
2275 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_LOADED;
2276 model_begin_loading (model, node);
2277
2278 dir->cancellable = g_cancellable_new ();
2279
2280 async = g_new (AsyncNode, 1)(AsyncNode *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (AsyncNode); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
2281 async->dir = dir;
2282 async->cancellable = g_object_ref (dir->cancellable)((__typeof__ (dir->cancellable)) (g_object_ref) (dir->cancellable
))
;
2283 async->original_children = g_slist_copy (dir->children);
2284
2285 /* Start loading async */
2286 g_file_enumerate_children_async (node->file,
2287 STANDARD_ATTRIBUTE_TYPES"standard::type" "," "standard::is-hidden" "," "standard::is-backup"
"," "standard::name" "," "standard::content-type" "," "standard::icon"
,
2288 G_FILE_QUERY_INFO_NONE,
2289 G_PRIORITY_DEFAULT0,
2290 async->cancellable,
2291 (GAsyncReadyCallback)model_iterate_children_cb,
2292 async);
2293}
2294
2295static GList *
2296get_parent_files (PlumaFileBrowserStore * model, GFile * file)
2297{
2298 GList * result = NULL((void*)0);
2299
2300 result = g_list_prepend (result, g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)));
2301
2302 while ((file = g_file_get_parent (file))) {
2303 if (g_file_equal (file, model->priv->root->file)) {
2304 g_object_unref (file);
2305 break;
2306 }
2307
2308 result = g_list_prepend (result, file);
2309 }
2310
2311 return result;
2312}
2313
2314static void
2315model_fill (PlumaFileBrowserStore * model, FileBrowserNode * node,
2316 GtkTreePath ** path)
2317{
2318 gboolean free_path = FALSE(0);
2319 GtkTreeIter iter = {0,};
2320 GSList *item;
2321 FileBrowserNode *child;
2322
2323 if (node == NULL((void*)0)) {
2324 node = model->priv->virtual_root;
2325 *path = gtk_tree_path_new ();
2326 free_path = TRUE(!(0));
2327 }
2328
2329 if (*path == NULL((void*)0)) {
2330 *path =
2331 pluma_file_browser_store_get_path_real (model, node);
2332 free_path = TRUE(!(0));
2333 }
2334
2335 if (!model_node_visibility (model, node)) {
2336 if (free_path)
2337 gtk_tree_path_free (*path);
2338
2339 return;
2340 }
2341
2342 if (node != model->priv->virtual_root) {
2343 /* Insert node */
2344 iter.user_data = node;
2345
2346 row_inserted(model, path, &iter);
2347 }
2348
2349 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
2350 /* Go to the first child */
2351 gtk_tree_path_down (*path);
2352
2353 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item;
2354 item = item->next) {
2355 child = (FileBrowserNode *) (item->data);
2356
2357 if (model_node_visibility (model, child)) {
2358 model_fill (model, child, path);
2359
2360 /* Increase path for next child */
2361 gtk_tree_path_next (*path);
2362 }
2363 }
2364
2365 /* Move back up to node path */
2366 gtk_tree_path_up (*path);
2367 }
2368
2369 model_check_dummy (model, node);
2370
2371 if (free_path)
2372 gtk_tree_path_free (*path);
2373}
2374
2375static void
2376set_virtual_root_from_node (PlumaFileBrowserStore * model,
2377 FileBrowserNode * node)
2378{
2379 FileBrowserNode *next;
2380 FileBrowserNode *prev;
2381 FileBrowserNode *check;
2382 FileBrowserNodeDir *dir;
2383 GSList *item;
2384 GSList *copy;
2385 GtkTreePath *empty = NULL((void*)0);
2386
2387 g_assert (node != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_219
; if (node != ((void*)0)) _g_boolean_var_219 = 1; else _g_boolean_var_219
= 0; _g_boolean_var_219; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "pluma-file-browser-store.c", 2387, ((const char
*) (__func__)), "node != NULL"); } while (0)
;
2388
2389 prev = node;
2390 next = prev->parent;
2391
2392 /* Free all the nodes below that we don't need in cache */
2393 while (prev != model->priv->root) {
2394 dir = FILE_BROWSER_NODE_DIR (next)((FileBrowserNodeDir *)(next));
2395 copy = g_slist_copy (dir->children);
2396
2397 for (item = copy; item; item = item->next) {
2398 check = (FileBrowserNode *) (item->data);
2399
2400 if (prev == node) {
2401 /* Only free the children, keeping this depth in cache */
2402 if (check != node) {
2403 file_browser_node_free_children
2404 (model, check);
2405 file_browser_node_unload (model,
2406 check,
2407 FALSE(0));
2408 }
2409 } else if (check != prev) {
2410 /* Only free when the node is not in the chain */
2411 dir->children =
2412 g_slist_remove (dir->children, check);
2413 file_browser_node_free (model, check);
2414 }
2415 }
2416
2417 if (prev != node)
2418 file_browser_node_unload (model, next, FALSE(0));
2419
2420 g_slist_free (copy);
2421 prev = next;
2422 next = prev->parent;
2423 }
2424
2425 /* Free all the nodes up that we don't need in cache */
2426 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item;
2427 item = item->next) {
2428 check = (FileBrowserNode *) (item->data);
2429
2430 if (NODE_IS_DIR (check)(((check)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
2431 for (copy =
2432 FILE_BROWSER_NODE_DIR (check)((FileBrowserNodeDir *)(check))->children; copy;
2433 copy = copy->next) {
2434 file_browser_node_free_children (model,
2435 (FileBrowserNode
2436 *)
2437 (copy->
2438 data));
2439 file_browser_node_unload (model,
2440 (FileBrowserNode
2441 *) (copy->data),
2442 FALSE(0));
2443 }
2444 } else if (NODE_IS_DUMMY (check)(((check)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
) {
2445 check->flags |=
2446 PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
2447 }
2448 }
2449
2450 /* Now finally, set the virtual root, and load it up! */
2451 model->priv->virtual_root = node;
2452
2453 /* Notify that the virtual-root has changed before loading up new nodes so that the
2454 "root_changed" signal can be emitted before any "inserted" signals */
2455 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "virtual-root");
2456
2457 model_fill (model, NULL((void*)0), &empty);
2458
2459 if (!NODE_LOADED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
)
2460 model_load_directory (model, node);
2461}
2462
2463static void
2464set_virtual_root_from_file (PlumaFileBrowserStore * model,
2465 GFile * file)
2466{
2467 GList * files;
2468 GList * item;
2469 FileBrowserNode * parent;
2470 GFile * check;
2471
2472 /* Always clear the model before altering the nodes */
2473 model_clear (model, FALSE(0));
2474
2475 /* Create the node path, get all the uri's */
2476 files = get_parent_files (model, file);
2477 parent = model->priv->root;
2478
2479 for (item = files; item; item = item->next) {
2480 check = G_FILE (item->data)((((GFile*) (void *) ((item->data)))));
2481
2482 parent = model_add_node_from_dir (model, parent, check);
2483 g_object_unref (check);
2484 }
2485
2486 g_list_free (files);
2487 set_virtual_root_from_node (model, parent);
2488}
2489
2490static FileBrowserNode *
2491model_find_node_children (PlumaFileBrowserStore * model,
2492 FileBrowserNode * parent,
2493 GFile * file)
2494{
2495 FileBrowserNodeDir *dir;
2496 FileBrowserNode *child;
2497 FileBrowserNode *result;
2498 GSList *children;
2499
2500 if (!NODE_IS_DIR (parent)(((parent)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
2501 return NULL((void*)0);
2502
2503 dir = FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent));
2504
2505 for (children = dir->children; children; children = children->next) {
2506 child = (FileBrowserNode *)(children->data);
2507
2508 result = model_find_node (model, child, file);
2509
2510 if (result)
2511 return result;
2512 }
2513
2514 return NULL((void*)0);
2515}
2516
2517static FileBrowserNode *
2518model_find_node (PlumaFileBrowserStore * model,
2519 FileBrowserNode * node,
2520 GFile * file)
2521{
2522 if (node == NULL((void*)0))
2523 node = model->priv->root;
2524
2525 if (node->file && g_file_equal (node->file, file))
2526 return node;
2527
2528 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
&& g_file_has_prefix (file, node->file))
2529 return model_find_node_children (model, node, file);
2530
2531 return NULL((void*)0);
2532}
2533
2534static GQuark
2535pluma_file_browser_store_error_quark (void)
2536{
2537 static GQuark quark = 0;
2538
2539 if (G_UNLIKELY (quark == 0)(__builtin_expect (__extension__ ({ int _g_boolean_var_220; if
(quark == 0) _g_boolean_var_220 = 1; else _g_boolean_var_220
= 0; _g_boolean_var_220; }), 0))
) {
2540 quark = g_quark_from_string ("pluma_file_browser_store_error");
2541 }
2542
2543 return quark;
2544}
2545
2546static GFile *
2547unique_new_name (GFile * directory, gchar const * name)
2548{
2549 GFile * newuri = NULL((void*)0);
2550 guint num = 0;
2551 gchar * newname;
2552
2553 while (newuri == NULL((void*)0) || g_file_query_exists (newuri, NULL((void*)0))) {
2554 if (newuri != NULL((void*)0))
2555 g_object_unref (newuri);
2556
2557 if (num == 0)
2558 newname = g_strdup (name)g_strdup_inline (name);
2559 else
2560 newname = g_strdup_printf ("%s(%d)", name, num);
2561
2562 newuri = g_file_get_child (directory, newname);
2563 g_free (newname);
2564
2565 ++num;
2566 }
2567
2568 return newuri;
2569}
2570
2571static PlumaFileBrowserStoreResult
2572model_root_mounted (PlumaFileBrowserStore * model, gchar const * virtual_root)
2573{
2574 model_check_dummy (model, model->priv->root);
2575 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "root");
2576
2577 if (virtual_root != NULL((void*)0))
2578 return
2579 pluma_file_browser_store_set_virtual_root_from_string
2580 (model, virtual_root);
2581 else
2582 set_virtual_root_from_node (model,
2583 model->priv->root);
2584
2585 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2586}
2587
2588static void
2589handle_root_error (PlumaFileBrowserStore * model, GError *error)
2590{
2591 FileBrowserNode * root;
2592
2593 g_signal_emit (model,
2594 model_signals[ERROR],
2595 0,
2596 PLUMA_FILE_BROWSER_ERROR_SET_ROOT,
2597 error->message);
2598
2599 /* Set the virtual root to the root */
2600 root = model->priv->root;
2601 model->priv->virtual_root = root;
2602
2603 /* Set the root to be loaded */
2604 root->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_LOADED;
2605
2606 /* Check the dummy */
2607 model_check_dummy (model, root);
2608
2609 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "root");
2610 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "virtual-root");
2611}
2612
2613static void
2614mount_cb (GFile * file,
2615 GAsyncResult * res,
2616 MountInfo * mount_info)
2617{
2618 gboolean mounted;
2619 GError * error = NULL((void*)0);
2620 PlumaFileBrowserStore * model = mount_info->model;
2621
2622 mounted = g_file_mount_enclosing_volume_finish (file, res, &error);
2623
2624 if (mount_info->model)
2625 {
2626 model->priv->mount_info = NULL((void*)0);
2627 model_end_loading (model, model->priv->root);
2628 }
2629
2630 if (!mount_info->model || g_cancellable_is_cancelled (mount_info->cancellable))
2631 {
2632 // Reset because it might be reused?
2633 g_cancellable_reset (mount_info->cancellable);
2634 }
2635 else if (mounted)
2636 {
2637 model_root_mounted (model, mount_info->virtual_root);
2638 }
2639 else if (error->code != G_IO_ERROR_CANCELLED)
2640 {
2641 handle_root_error (model, error);
2642 }
2643
2644 if (error)
2645 g_error_free (error);
2646
2647 g_object_unref (mount_info->operation);
2648 g_object_unref (mount_info->cancellable);
2649 g_free (mount_info->virtual_root);
2650
2651 g_free (mount_info);
2652}
2653
2654static PlumaFileBrowserStoreResult
2655model_mount_root (PlumaFileBrowserStore * model, gchar const * virtual_root)
2656{
2657 GFileInfo * info;
2658 GError * error = NULL((void*)0);
2659 MountInfo * mount_info;
2660
2661 info = g_file_query_info (model->priv->root->file,
2662 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type",
2663 G_FILE_QUERY_INFO_NONE,
2664 NULL((void*)0),
2665 &error);
2666
2667 if (!info) {
2668 if (error->code == G_IO_ERROR_NOT_MOUNTED) {
2669 /* Try to mount it */
2670 FILE_BROWSER_NODE_DIR (model->priv->root)((FileBrowserNodeDir *)(model->priv->root))->cancellable = g_cancellable_new ();
2671
2672 mount_info = g_new(MountInfo, 1)(MountInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (MountInfo); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
2673 mount_info->model = model;
2674 mount_info->virtual_root = g_strdup (virtual_root)g_strdup_inline (virtual_root);
2675
2676 /* FIXME: we should be setting the correct window */
2677 mount_info->operation = gtk_mount_operation_new (NULL((void*)0));
2678 mount_info->cancellable = g_object_ref (FILE_BROWSER_NODE_DIR (model->priv->root)->cancellable)((__typeof__ (((FileBrowserNodeDir *)(model->priv->root
))->cancellable)) (g_object_ref) (((FileBrowserNodeDir *)(
model->priv->root))->cancellable))
;
2679
2680 model_begin_loading (model, model->priv->root);
2681 g_file_mount_enclosing_volume (model->priv->root->file,
2682 G_MOUNT_MOUNT_NONE,
2683 mount_info->operation,
2684 mount_info->cancellable,
2685 (GAsyncReadyCallback)mount_cb,
2686 mount_info);
2687
2688 model->priv->mount_info = mount_info;
2689 return PLUMA_FILE_BROWSER_STORE_RESULT_MOUNTING;
2690 }
2691 else
2692 {
2693 handle_root_error (model, error);
2694 }
2695
2696 g_error_free (error);
2697 } else {
2698 g_object_unref (info);
2699
2700 return model_root_mounted (model, virtual_root);
2701 }
2702
2703 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2704}
2705
2706/* Public */
2707PlumaFileBrowserStore *
2708pluma_file_browser_store_new (gchar const *root)
2709{
2710 PlumaFileBrowserStore *obj =
2711 PLUMA_FILE_BROWSER_STORE (g_object_new((((PlumaFileBrowserStore*) (void *) ((g_object_new ((pluma_file_browser_store_get_type
()), ((void*)0)))))))
2712 (PLUMA_TYPE_FILE_BROWSER_STORE,((((PlumaFileBrowserStore*) (void *) ((g_object_new ((pluma_file_browser_store_get_type
()), ((void*)0)))))))
2713 NULL))((((PlumaFileBrowserStore*) (void *) ((g_object_new ((pluma_file_browser_store_get_type
()), ((void*)0)))))))
;
2714
2715 pluma_file_browser_store_set_root (obj, root);
2716 return obj;
2717}
2718
2719void
2720pluma_file_browser_store_set_value (PlumaFileBrowserStore * tree_model,
2721 GtkTreeIter * iter, gint column,
2722 GValue * value)
2723{
2724 gpointer data;
2725 FileBrowserNode *node;
2726 GtkTreePath *path;
2727
2728 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_221
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_221 = 1; else _g_boolean_var_221 =
0; _g_boolean_var_221; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return; } } while (0)
;
2729 g_return_if_fail (column ==do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_222
; if (column == PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM) _g_boolean_var_222
= 1; else _g_boolean_var_222 = 0; _g_boolean_var_222; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "column == PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM"
); return; } } while (0)
2730 PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_222
; if (column == PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM) _g_boolean_var_222
= 1; else _g_boolean_var_222 = 0; _g_boolean_var_222; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "column == PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM"
); return; } } while (0)
;
2731 g_return_if_fail (G_VALUE_HOLDS_OBJECT (value))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_223
; if ((((__extension__ ({ const GValue *__val = (const GValue
*) ((value)); GType __t = (((GType) ((20) << (2)))); gboolean
__r; if (!__val) __r = (0); else if (__val->g_type == __t
) __r = (!(0)); else __r = g_type_check_value_holds (__val, __t
); __r; }))))) _g_boolean_var_223 = 1; else _g_boolean_var_223
= 0; _g_boolean_var_223; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "G_VALUE_HOLDS_OBJECT (value)"
); return; } } while (0)
;
2732 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_224
; if (iter != ((void*)0)) _g_boolean_var_224 = 1; else _g_boolean_var_224
= 0; _g_boolean_var_224; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
2733 g_return_if_fail (iter->user_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_225
; if (iter->user_data != ((void*)0)) _g_boolean_var_225 = 1
; else _g_boolean_var_225 = 0; _g_boolean_var_225; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return; } } while
(0)
;
2734
2735 data = g_value_get_object (value);
2736
2737 if (data)
2738 g_return_if_fail (GDK_IS_PIXBUF (data))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_226
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((data)); GType __t = ((gdk_pixbuf_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_226
= 1; else _g_boolean_var_226 = 0; _g_boolean_var_226; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "GDK_IS_PIXBUF (data)"); return; } } while
(0)
;
2739
2740 node = (FileBrowserNode *) (iter->user_data);
2741
2742 if (node->emblem)
2743 g_object_unref (node->emblem);
2744
2745 if (data)
2746 node->emblem = g_object_ref (GDK_PIXBUF (data))((__typeof__ (((((GdkPixbuf*) (void *) ((data))))))) (g_object_ref
) (((((GdkPixbuf*) (void *) ((data)))))))
;
2747 else
2748 node->emblem = NULL((void*)0);
2749
2750 model_recomposite_icon (tree_model, iter);
2751
2752 if (model_node_visibility (tree_model, node)) {
2753 path = pluma_file_browser_store_get_path (GTK_TREE_MODEL (tree_model)((((GtkTreeModel*) (void *) ((tree_model))))),
2754 iter);
2755 row_changed (tree_model, &path, iter);
2756 gtk_tree_path_free (path);
2757 }
2758}
2759
2760PlumaFileBrowserStoreResult
2761pluma_file_browser_store_set_virtual_root (PlumaFileBrowserStore * model,
2762 GtkTreeIter * iter)
2763{
2764 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_227
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_227 = 1; else _g_boolean_var_227 =
0; _g_boolean_var_227; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2765 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_227
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_227 = 1; else _g_boolean_var_227 =
0; _g_boolean_var_227; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2766 g_return_val_if_fail (iter != NULL,do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_228
; if (iter != ((void*)0)) _g_boolean_var_228 = 1; else _g_boolean_var_228
= 0; _g_boolean_var_228; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
(PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while (0)
2767 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_228
; if (iter != ((void*)0)) _g_boolean_var_228 = 1; else _g_boolean_var_228
= 0; _g_boolean_var_228; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
(PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while (0)
;
2768 g_return_val_if_fail (iter->user_data != NULL,do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_229
; if (iter->user_data != ((void*)0)) _g_boolean_var_229 = 1
; else _g_boolean_var_229 = 0; _g_boolean_var_229; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE
); } } while (0)
2769 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_229
; if (iter->user_data != ((void*)0)) _g_boolean_var_229 = 1
; else _g_boolean_var_229 = 0; _g_boolean_var_229; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE
); } } while (0)
;
2770
2771 model_clear (model, FALSE(0));
2772 set_virtual_root_from_node (model,
2773 (FileBrowserNode *) (iter->user_data));
2774
2775 return TRUE(!(0));
2776}
2777
2778PlumaFileBrowserStoreResult
2779pluma_file_browser_store_set_virtual_root_from_string
2780 (PlumaFileBrowserStore * model, gchar const *root) {
2781 GFile *file;
2782
2783 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_230
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_230 = 1; else _g_boolean_var_230 =
0; _g_boolean_var_230; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2784 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_230
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_230 = 1; else _g_boolean_var_230 =
0; _g_boolean_var_230; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2785
2786 file = g_file_new_for_uri (root);
2787 if (file == NULL((void*)0)) {
2788 g_warning ("Invalid uri (%s)", root);
2789 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2790 }
2791
2792 /* Check if uri is already the virtual root */
2793 if (model->priv->virtual_root &&
2794 g_file_equal (model->priv->virtual_root->file, file)) {
2795 g_object_unref (file);
2796 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2797 }
2798
2799 /* Check if uri is the root itself */
2800 if (g_file_equal (model->priv->root->file, file)) {
2801 g_object_unref (file);
2802
2803 /* Always clear the model before altering the nodes */
2804 model_clear (model, FALSE(0));
2805 set_virtual_root_from_node (model, model->priv->root);
2806 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2807 }
2808
2809 if (!g_file_has_prefix (file, model->priv->root->file)) {
2810 gchar *str, *str1;
2811
2812 str = g_file_get_parse_name (model->priv->root->file);
2813 str1 = g_file_get_parse_name (file);
2814
2815 g_warning
2816 ("Virtual root (%s) is not below actual root (%s)",
2817 str1, str);
2818
2819 g_free (str);
2820 g_free (str1);
2821
2822 g_object_unref (file);
2823 return PLUMA_FILE_BROWSER_STORE_RESULT_ERROR;
2824 }
2825
2826 set_virtual_root_from_file (model, file);
2827 g_object_unref (file);
2828
2829 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2830}
2831
2832PlumaFileBrowserStoreResult
2833pluma_file_browser_store_set_virtual_root_top (PlumaFileBrowserStore *
2834 model)
2835{
2836 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_231
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_231 = 1; else _g_boolean_var_231 =
0; _g_boolean_var_231; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2837 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_231
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_231 = 1; else _g_boolean_var_231 =
0; _g_boolean_var_231; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2838
2839 if (model->priv->virtual_root == model->priv->root)
2840 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2841
2842 model_clear (model, FALSE(0));
2843 set_virtual_root_from_node (model, model->priv->root);
2844
2845 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2846}
2847
2848PlumaFileBrowserStoreResult
2849pluma_file_browser_store_set_virtual_root_up (PlumaFileBrowserStore *
2850 model)
2851{
2852 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_232
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_232 = 1; else _g_boolean_var_232 =
0; _g_boolean_var_232; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2853 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_232
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_232 = 1; else _g_boolean_var_232 =
0; _g_boolean_var_232; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2854
2855 if (model->priv->virtual_root == model->priv->root)
2856 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2857
2858 model_clear (model, FALSE(0));
2859 set_virtual_root_from_node (model,
2860 model->priv->virtual_root->parent);
2861
2862 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2863}
2864
2865gboolean
2866pluma_file_browser_store_get_iter_virtual_root (PlumaFileBrowserStore *
2867 model, GtkTreeIter * iter)
2868{
2869 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_233
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_233 = 1; else _g_boolean_var_233 =
0; _g_boolean_var_233; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
2870 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_234
; if (iter != ((void*)0)) _g_boolean_var_234 = 1; else _g_boolean_var_234
= 0; _g_boolean_var_234; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
2871
2872 if (model->priv->virtual_root == NULL((void*)0))
2873 return FALSE(0);
2874
2875 iter->user_data = model->priv->virtual_root;
2876 return TRUE(!(0));
2877}
2878
2879gboolean
2880pluma_file_browser_store_get_iter_root (PlumaFileBrowserStore * model,
2881 GtkTreeIter * iter)
2882{
2883 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_235
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_235 = 1; else _g_boolean_var_235 =
0; _g_boolean_var_235; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
2884 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_236
; if (iter != ((void*)0)) _g_boolean_var_236 = 1; else _g_boolean_var_236
= 0; _g_boolean_var_236; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
2885
2886 if (model->priv->root == NULL((void*)0))
2887 return FALSE(0);
2888
2889 iter->user_data = model->priv->root;
2890 return TRUE(!(0));
2891}
2892
2893gboolean
2894pluma_file_browser_store_iter_equal (PlumaFileBrowserStore * model,
2895 GtkTreeIter * iter1,
2896 GtkTreeIter * iter2)
2897{
2898 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_237
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_237 = 1; else _g_boolean_var_237 =
0; _g_boolean_var_237; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
2899 g_return_val_if_fail (iter1 != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_238
; if (iter1 != ((void*)0)) _g_boolean_var_238 = 1; else _g_boolean_var_238
= 0; _g_boolean_var_238; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter1 != NULL");
return ((0)); } } while (0)
;
2900 g_return_val_if_fail (iter2 != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_239
; if (iter2 != ((void*)0)) _g_boolean_var_239 = 1; else _g_boolean_var_239
= 0; _g_boolean_var_239; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter2 != NULL");
return ((0)); } } while (0)
;
2901 g_return_val_if_fail (iter1->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_240
; if (iter1->user_data != ((void*)0)) _g_boolean_var_240 =
1; else _g_boolean_var_240 = 0; _g_boolean_var_240; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter1->user_data != NULL"); return ((0));
} } while (0)
;
2902 g_return_val_if_fail (iter2->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_241
; if (iter2->user_data != ((void*)0)) _g_boolean_var_241 =
1; else _g_boolean_var_241 = 0; _g_boolean_var_241; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter2->user_data != NULL"); return ((0));
} } while (0)
;
2903
2904 return (iter1->user_data == iter2->user_data);
2905}
2906
2907void
2908pluma_file_browser_store_cancel_mount_operation (PlumaFileBrowserStore *store)
2909{
2910 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (store))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_242
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((store)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_242 = 1; else _g_boolean_var_242 =
0; _g_boolean_var_242; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (store)"
); return; } } while (0)
;
2911
2912 cancel_mount_operation (store);
2913}
2914
2915PlumaFileBrowserStoreResult
2916pluma_file_browser_store_set_root_and_virtual_root (PlumaFileBrowserStore *
2917 model,
2918 gchar const *root,
2919 gchar const *virtual_root)
2920{
2921 GFile * file = NULL((void*)0);
2922 GFile * vfile = NULL((void*)0);
2923 FileBrowserNode * node;
2924 gboolean equal = FALSE(0);
2925
2926 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_243
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_243 = 1; else _g_boolean_var_243 =
0; _g_boolean_var_243; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2927 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_243
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_243 = 1; else _g_boolean_var_243 =
0; _g_boolean_var_243; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2928
2929 if (root == NULL((void*)0) && model->priv->root == NULL((void*)0))
2930 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2931
2932 if (root != NULL((void*)0)) {
2933 file = g_file_new_for_uri (root);
2934 }
2935
2936 if (root != NULL((void*)0) && model->priv->root != NULL((void*)0)) {
2937 equal = g_file_equal (file, model->priv->root->file);
2938
2939 if (equal && virtual_root == NULL((void*)0)) {
2940 g_object_unref (file);
2941 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2942 }
2943 }
2944
2945 if (virtual_root) {
2946 vfile = g_file_new_for_uri (virtual_root);
2947
2948 if (equal && g_file_equal (vfile, model->priv->virtual_root->file)) {
2949 if (file)
2950 g_object_unref (file);
2951
2952 g_object_unref (vfile);
2953 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2954 }
2955
2956 g_object_unref (vfile);
2957 }
2958
2959 /* make sure to cancel any previous mount operations */
2960 cancel_mount_operation (model);
2961
2962 /* Always clear the model before altering the nodes */
2963 model_clear (model, TRUE(!(0)));
2964 file_browser_node_free (model, model->priv->root);
2965
2966 model->priv->root = NULL((void*)0);
2967 model->priv->virtual_root = NULL((void*)0);
2968
2969 if (file != NULL((void*)0)) {
2970 /* Create the root node */
2971 node = file_browser_node_dir_new (model, file, NULL((void*)0));
2972
2973 g_object_unref (file);
2974
2975 model->priv->root = node;
2976 return model_mount_root (model, virtual_root);
2977 } else {
2978 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "root");
2979 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "virtual-root");
2980 }
2981
2982 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2983}
2984
2985PlumaFileBrowserStoreResult
2986pluma_file_browser_store_set_root (PlumaFileBrowserStore * model,
2987 gchar const *root)
2988{
2989 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_244
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_244 = 1; else _g_boolean_var_244 =
0; _g_boolean_var_244; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2990 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_244
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_244 = 1; else _g_boolean_var_244 =
0; _g_boolean_var_244; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2991 return pluma_file_browser_store_set_root_and_virtual_root (model,
2992 root,
2993 NULL((void*)0));
2994}
2995
2996gchar *
2997pluma_file_browser_store_get_root (PlumaFileBrowserStore * model)
2998{
2999 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_245
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_245 = 1; else _g_boolean_var_245 =
0; _g_boolean_var_245; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (((void*)0)); } } while (0)
;
3000
3001 if (model->priv->root == NULL((void*)0) || model->priv->root->file == NULL((void*)0))
3002 return NULL((void*)0);
3003 else
3004 return g_file_get_uri (model->priv->root->file);
3005}
3006
3007gchar *
3008pluma_file_browser_store_get_virtual_root (PlumaFileBrowserStore * model)
3009{
3010 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_246
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_246 = 1; else _g_boolean_var_246 =
0; _g_boolean_var_246; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (((void*)0)); } } while (0)
;
3011
3012 if (model->priv->virtual_root == NULL((void*)0) || model->priv->virtual_root->file == NULL((void*)0))
3013 return NULL((void*)0);
3014 else
3015 return g_file_get_uri (model->priv->virtual_root->file);
3016}
3017
3018void
3019_pluma_file_browser_store_iter_expanded (PlumaFileBrowserStore * model,
3020 GtkTreeIter * iter)
3021{
3022 FileBrowserNode *node;
3023
3024 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_247
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_247 = 1; else _g_boolean_var_247 =
0; _g_boolean_var_247; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return; } } while (0)
;
3025 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_248
; if (iter != ((void*)0)) _g_boolean_var_248 = 1; else _g_boolean_var_248
= 0; _g_boolean_var_248; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
3026 g_return_if_fail (iter->user_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_249
; if (iter->user_data != ((void*)0)) _g_boolean_var_249 = 1
; else _g_boolean_var_249 = 0; _g_boolean_var_249; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return; } } while
(0)
;
3027
3028 node = (FileBrowserNode *) (iter->user_data);
3029
3030 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
&& !NODE_LOADED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
) {
3031 /* Load it now */
3032 model_load_directory (model, node);
3033 }
3034}
3035
3036void
3037_pluma_file_browser_store_iter_collapsed (PlumaFileBrowserStore * model,
3038 GtkTreeIter * iter)
3039{
3040 FileBrowserNode *node;
3041 GSList *item;
3042
3043 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_250
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_250 = 1; else _g_boolean_var_250 =
0; _g_boolean_var_250; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return; } } while (0)
;
3044 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_251
; if (iter != ((void*)0)) _g_boolean_var_251 = 1; else _g_boolean_var_251
= 0; _g_boolean_var_251; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
3045 g_return_if_fail (iter->user_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_252
; if (iter->user_data != ((void*)0)) _g_boolean_var_252 = 1
; else _g_boolean_var_252 = 0; _g_boolean_var_252; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return; } } while
(0)
;
3046
3047 node = (FileBrowserNode *) (iter->user_data);
3048
3049 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
&& NODE_LOADED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
) {
3050 /* Unload children of the children, keeping 1 depth in cache */
3051
3052 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item;
3053 item = item->next) {
3054 node = (FileBrowserNode *) (item->data);
3055
3056 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
&& NODE_LOADED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
) {
3057 file_browser_node_unload (model, node,
3058 TRUE(!(0)));
3059 model_check_dummy (model, node);
3060 }
3061 }
3062 }
3063}
3064
3065PlumaFileBrowserStoreFilterMode
3066pluma_file_browser_store_get_filter_mode (PlumaFileBrowserStore * model)
3067{
3068 return model->priv->filter_mode;
3069}
3070
3071void
3072pluma_file_browser_store_set_filter_mode (PlumaFileBrowserStore * model,
3073 PlumaFileBrowserStoreFilterMode
3074 mode)
3075{
3076 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_253
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_253 = 1; else _g_boolean_var_253 =
0; _g_boolean_var_253; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return; } } while (0)
;
3077
3078 if (model->priv->filter_mode == mode)
3079 return;
3080
3081 model->priv->filter_mode = mode;
3082 model_refilter (model);
3083
3084 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "filter-mode");
3085}
3086
3087void
3088pluma_file_browser_store_set_filter_func (PlumaFileBrowserStore * model,
3089 PlumaFileBrowserStoreFilterFunc
3090 func, gpointer user_data)
3091{
3092 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_254
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_254 = 1; else _g_boolean_var_254 =
0; _g_boolean_var_254; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return; } } while (0)
;
3093
3094 model->priv->filter_func = func;
3095 model->priv->filter_user_data = user_data;
3096 model_refilter (model);
3097}
3098
3099void
3100pluma_file_browser_store_refilter (PlumaFileBrowserStore * model)
3101{
3102 model_refilter (model);
3103}
3104
3105PlumaFileBrowserStoreFilterMode
3106pluma_file_browser_store_filter_mode_get_default (void)
3107{
3108 return PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_HIDDEN;
3109}
3110
3111void
3112pluma_file_browser_store_refresh (PlumaFileBrowserStore * model)
3113{
3114 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_255
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_255 = 1; else _g_boolean_var_255 =
0; _g_boolean_var_255; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return; } } while (0)
;
3115
3116 if (model->priv->root == NULL((void*)0) || model->priv->virtual_root == NULL((void*)0))
3117 return;
3118
3119 /* Clear the model */
3120 g_signal_emit (model, model_signals[BEGIN_REFRESH], 0);
3121 file_browser_node_unload (model, model->priv->virtual_root, TRUE(!(0)));
3122 model_load_directory (model, model->priv->virtual_root);
3123 g_signal_emit (model, model_signals[END_REFRESH], 0);
3124}
3125
3126static void
3127reparent_node (FileBrowserNode * node, gboolean reparent)
3128{
3129 FileBrowserNodeDir * dir;
3130 GSList * child;
3131 GFile * parent;
3132 gchar * base;
3133
3134 if (!node->file) {
3135 return;
3136 }
3137
3138 if (reparent) {
3139 parent = node->parent->file;
3140 base = g_file_get_basename (node->file);
3141 g_object_unref (node->file);
3142
3143 node->file = g_file_get_child (parent, base);
3144 g_free (base);
3145 }
3146
3147 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
3148 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
3149
3150 for (child = dir->children; child; child = child->next) {
3151 reparent_node ((FileBrowserNode *)child->data, TRUE(!(0)));
3152 }
3153 }
3154}
3155
3156gboolean
3157pluma_file_browser_store_rename (PlumaFileBrowserStore * model,
3158 GtkTreeIter * iter,
3159 const gchar * new_name,
3160 GError ** error)
3161{
3162 FileBrowserNode *node;
3163 GFile * file;
3164 GFile * parent;
3165 GFile * previous;
3166 GError * err = NULL((void*)0);
3167 gchar * olduri;
3168 gchar * newuri;
3169 GtkTreePath *path;
3170
3171 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_256
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_256 = 1; else _g_boolean_var_256 =
0; _g_boolean_var_256; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
1
Assuming '__inst' is non-null
2
Taking false branch
3
Assuming field 'g_class' is null
4
Assuming the condition is true
5
Taking true branch
6
Taking true branch
7
Loop condition is false. Exiting loop
3172 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_257
; if (iter != ((void*)0)) _g_boolean_var_257 = 1; else _g_boolean_var_257
= 0; _g_boolean_var_257; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
8
Assuming 'iter' is not equal to null
9
Taking true branch
10
Taking true branch
11
Loop condition is false. Exiting loop
3173 g_return_val_if_fail (iter->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_258
; if (iter->user_data != ((void*)0)) _g_boolean_var_258 = 1
; else _g_boolean_var_258 = 0; _g_boolean_var_258; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return ((0)); }
} while (0)
;
12
Assuming field 'user_data' is not equal to null
13
Taking true branch
14
Taking true branch
15
Loop condition is false. Exiting loop
3174
3175 node = (FileBrowserNode *) (iter->user_data);
3176
3177 parent = g_file_get_parent (node->file);
3178 g_return_val_if_fail (parent != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_259
; if (parent != ((void*)0)) _g_boolean_var_259 = 1; else _g_boolean_var_259
= 0; _g_boolean_var_259; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "parent != NULL")
; return ((0)); } } while (0)
;
16
Assuming 'parent' is not equal to null
17
Taking true branch
18
Taking true branch
19
Loop condition is false. Exiting loop
3179
3180 file = g_file_get_child (parent, new_name);
3181 g_object_unref (parent);
3182
3183 if (g_file_equal (node->file, file)) {
20
Assuming the condition is false
21
Taking false branch
3184 g_object_unref (file);
3185 return TRUE(!(0));
3186 }
3187
3188 if (g_file_move (node->file, file, G_FILE_COPY_NONE, NULL((void*)0), NULL((void*)0), NULL((void*)0), &err)) {
22
Assuming the condition is true
23
Taking true branch
3189 previous = node->file;
3190 node->file = file;
3191
3192 /* This makes sure the actual info for the node is requeried */
3193 file_browser_node_set_name (node);
3194 file_browser_node_set_from_info (model, node, NULL((void*)0), TRUE(!(0)));
3195
3196 reparent_node (node, FALSE(0));
3197
3198 if (model_node_visibility (model, node)) {
24
Taking true branch
3199 path = pluma_file_browser_store_get_path_real (model, node);
3200 row_changed (model, &path, iter);
3201 gtk_tree_path_free (path);
3202
3203 /* Reorder this item */
3204 model_resort_node (model, node);
25
Calling 'model_resort_node'
3205 } else {
3206 g_object_unref (previous);
3207
3208 if (error != NULL((void*)0))
3209 *error = g_error_new_literal (pluma_file_browser_store_error_quark (),
3210 PLUMA_FILE_BROWSER_ERROR_RENAME,
3211 _("The renamed file is currently filtered out. You need to adjust your filter settings to make the file visible")((char *) g_dgettext ("pluma", "The renamed file is currently filtered out. You need to adjust your filter settings to make the file visible"
))
);
3212 return FALSE(0);
3213 }
3214
3215 olduri = g_file_get_uri (previous);
3216 newuri = g_file_get_uri (node->file);
3217
3218 g_signal_emit (model, model_signals[RENAME], 0, olduri, newuri);
3219
3220 g_object_unref (previous);
3221 g_free (olduri);
3222 g_free (newuri);
3223
3224 return TRUE(!(0));
3225 } else {
3226 g_object_unref (file);
3227
3228 if (err) {
3229 if (error != NULL((void*)0)) {
3230 *error =
3231 g_error_new_literal
3232 (pluma_file_browser_store_error_quark (),
3233 PLUMA_FILE_BROWSER_ERROR_RENAME,
3234 err->message);
3235 }
3236
3237 g_error_free (err);
3238 }
3239
3240 return FALSE(0);
3241 }
3242}
3243
3244static void
3245async_data_free (AsyncData * data)
3246{
3247 g_object_unref (data->cancellable);
3248
3249 g_list_free_full (data->files, g_object_unref);
3250
3251 if (!data->removed)
3252 data->model->priv->async_handles = g_slist_remove (data->model->priv->async_handles, data);
3253
3254 g_free (data);
3255}
3256
3257static gboolean
3258emit_no_trash (AsyncData * data)
3259{
3260 /* Emit the no trash error */
3261 gboolean ret;
3262
3263 g_signal_emit (data->model, model_signals[NO_TRASH], 0, data->files, &ret);
3264 return ret;
3265}
3266
3267static void
3268delete_file_finished (GFile *file,
3269 GAsyncResult *res,
3270 AsyncData *data)
3271{
3272 GError * error = NULL((void*)0);
3273 gboolean ok;
3274
3275 if (data->trash)
3276 {
3277 ok = g_file_trash_finish (file, res, &error);
3278 }
3279 else
3280 {
3281 ok = g_file_delete_finish (file, res, &error);
3282 }
3283
3284 if (ok)
3285 {
3286 /* Remove the file from the model */
3287 FileBrowserNode *node = model_find_node (data->model, NULL((void*)0), file);
3288
3289 if (node != NULL((void*)0))
3290 {
3291 model_remove_node (data->model, node, NULL((void*)0), TRUE(!(0)));
3292 }
3293
3294 /* Process the next file */
3295 data->iter = data->iter->next;
3296 }
3297 else if (!ok && error != NULL((void*)0))
3298 {
3299 gint code = error->code;
3300 g_error_free (error);
3301
3302 if (data->trash && code == G_IO_ERROR_NOT_SUPPORTED) {
3303 /* Trash is not supported on this system. Ask the user
3304 * if he wants to delete completely the files instead.
3305 */
3306 if (emit_no_trash (data))
3307 {
3308 /* Changes this into a delete job */
3309 data->trash = FALSE(0);
3310 data->iter = data->files;
3311 }
3312 else
3313 {
3314 /* End the job */
3315 async_data_free (data);
3316 return;
3317 }
3318 }
3319 else if (code == G_IO_ERROR_CANCELLED)
3320 {
3321 /* Job has been cancelled, end the job */
3322 async_data_free (data);
3323 return;
3324 }
3325 }
3326
3327 /* Continue the job */
3328 delete_files (data);
3329}
3330
3331static void
3332delete_files (AsyncData *data)
3333{
3334 GFile *file;
3335
3336 /* Check if our job is done */
3337 if (data->iter == NULL((void*)0))
3338 {
3339 async_data_free (data);
3340 return;
3341 }
3342
3343 file = G_FILE (data->iter->data)((((GFile*) (void *) ((data->iter->data)))));
3344
3345 if (data->trash)
3346 {
3347 g_file_trash_async (file,
3348 G_PRIORITY_DEFAULT0,
3349 data->cancellable,
3350 (GAsyncReadyCallback)delete_file_finished,
3351 data);
3352 }
3353 else
3354 {
3355 g_file_delete_async (file,
3356 G_PRIORITY_DEFAULT0,
3357 data->cancellable,
3358 (GAsyncReadyCallback)delete_file_finished,
3359 data);
3360 }
3361}
3362
3363PlumaFileBrowserStoreResult
3364pluma_file_browser_store_delete_all (PlumaFileBrowserStore *model,
3365 GList *rows, gboolean trash)
3366{
3367 FileBrowserNode * node;
3368 AsyncData * data;
3369 GList * files = NULL((void*)0);
3370 GList * row;
3371 GtkTreeIter iter;
3372 GtkTreePath * prev = NULL((void*)0);
3373 GtkTreePath * path;
3374
3375 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_260
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_260 = 1; else _g_boolean_var_260 =
0; _g_boolean_var_260; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
3376
3377 if (rows == NULL((void*)0))
3378 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
3379
3380 /* First we sort the paths so that we can later on remove any
3381 files/directories that are actually subfiles/directories of
3382 a directory that's also deleted */
3383 rows = g_list_sort (g_list_copy (rows), (GCompareFunc)gtk_tree_path_compare);
3384
3385 for (row = rows; row; row = row->next) {
3386 path = (GtkTreePath *)(row->data);
3387
3388 if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (model)((((GtkTreeModel*) (void *) ((model))))), &iter, path))
3389 continue;
3390
3391 /* Skip if the current path is actually a descendant of the
3392 previous path */
3393 if (prev != NULL((void*)0) && gtk_tree_path_is_descendant (path, prev))
3394 continue;
3395
3396 prev = path;
3397 node = (FileBrowserNode *)(iter.user_data);
3398 files = g_list_prepend (files, g_object_ref (node->file)((__typeof__ (node->file)) (g_object_ref) (node->file)));
3399 }
3400
3401 data = g_new (AsyncData, 1)(AsyncData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (AsyncData); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
3402
3403 data->model = model;
3404 data->cancellable = g_cancellable_new ();
3405 data->files = files;
3406 data->trash = trash;
3407 data->iter = files;
3408 data->removed = FALSE(0);
3409
3410 model->priv->async_handles =
3411 g_slist_prepend (model->priv->async_handles, data);
3412
3413 delete_files (data);
3414 g_list_free (rows);
3415
3416 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
3417}
3418
3419PlumaFileBrowserStoreResult
3420pluma_file_browser_store_delete (PlumaFileBrowserStore * model,
3421 GtkTreeIter * iter, gboolean trash)
3422{
3423 FileBrowserNode *node;
3424 GList *rows = NULL((void*)0);
3425 PlumaFileBrowserStoreResult result;
3426
3427 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_261
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_261 = 1; else _g_boolean_var_261 =
0; _g_boolean_var_261; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
3428 g_return_val_if_fail (iter != NULL, PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_262
; if (iter != ((void*)0)) _g_boolean_var_262 = 1; else _g_boolean_var_262
= 0; _g_boolean_var_262; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
(PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while (0)
;
3429 g_return_val_if_fail (iter->user_data != NULL, PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_263
; if (iter->user_data != ((void*)0)) _g_boolean_var_263 = 1
; else _g_boolean_var_263 = 0; _g_boolean_var_263; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE
); } } while (0)
;
3430
3431 node = (FileBrowserNode *) (iter->user_data);
3432
3433 if (NODE_IS_DUMMY (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
)
3434 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
3435
3436 rows = g_list_append(NULL((void*)0), pluma_file_browser_store_get_path_real (model, node));
3437 result = pluma_file_browser_store_delete_all (model, rows, trash);
3438
3439 g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free);
3440
3441 return result;
3442}
3443
3444gboolean
3445pluma_file_browser_store_new_file (PlumaFileBrowserStore * model,
3446 GtkTreeIter * parent,
3447 GtkTreeIter * iter)
3448{
3449 GFile * file;
3450 GFileOutputStream * stream;
3451 FileBrowserNodeDir *parent_node;
3452 gboolean result = FALSE(0);
3453 FileBrowserNode *node;
3454 GError * error = NULL((void*)0);
3455
3456 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_264
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_264 = 1; else _g_boolean_var_264 =
0; _g_boolean_var_264; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
3457 g_return_val_if_fail (parent != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_265
; if (parent != ((void*)0)) _g_boolean_var_265 = 1; else _g_boolean_var_265
= 0; _g_boolean_var_265; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "parent != NULL")
; return ((0)); } } while (0)
;
3458 g_return_val_if_fail (parent->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_266
; if (parent->user_data != ((void*)0)) _g_boolean_var_266 =
1; else _g_boolean_var_266 = 0; _g_boolean_var_266; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "parent->user_data != NULL"); return ((0))
; } } while (0)
;
3459 g_return_val_if_fail (NODE_IS_DIRdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_267
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_267
= 1; else _g_boolean_var_267 = 0; _g_boolean_var_267; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
3460 ((FileBrowserNode *) (parent->user_data)),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_267
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_267
= 1; else _g_boolean_var_267 = 0; _g_boolean_var_267; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
3461 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_267
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_267
= 1; else _g_boolean_var_267 = 0; _g_boolean_var_267; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
;
3462 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_268
; if (iter != ((void*)0)) _g_boolean_var_268 = 1; else _g_boolean_var_268
= 0; _g_boolean_var_268; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
3463
3464 parent_node = FILE_BROWSER_NODE_DIR (parent->user_data)((FileBrowserNodeDir *)(parent->user_data));
3465 /* Translators: This is the default name of new files created by the file browser pane. */
3466 file = unique_new_name (((FileBrowserNode *) parent_node)->file, _("file")((char *) g_dgettext ("pluma", "file")));
3467
3468 stream = g_file_create (file, G_FILE_CREATE_NONE, NULL((void*)0), &error);
3469
3470 if (!stream)
3471 {
3472 g_signal_emit (model, model_signals[ERROR], 0,
3473 PLUMA_FILE_BROWSER_ERROR_NEW_FILE,
3474 error->message);
3475 g_error_free (error);
3476 } else {
3477 g_object_unref (stream);
3478 node = model_add_node_from_file (model,
3479 (FileBrowserNode *)parent_node,
3480 file,
3481 NULL((void*)0));
3482
3483 if (model_node_visibility (model, node)) {
3484 iter->user_data = node;
3485 result = TRUE(!(0));
3486 } else {
3487 g_signal_emit (model, model_signals[ERROR], 0,
3488 PLUMA_FILE_BROWSER_ERROR_NEW_FILE,
3489 _((char *) g_dgettext ("pluma", "The new file is currently filtered out. You need to adjust your filter settings to make the file visible"
))
3490 ("The new file is currently filtered out. You need to adjust your filter settings to make the file visible")((char *) g_dgettext ("pluma", "The new file is currently filtered out. You need to adjust your filter settings to make the file visible"
))
);
3491 }
3492 }
3493
3494 g_object_unref (file);
3495 return result;
3496}
3497
3498gboolean
3499pluma_file_browser_store_new_directory (PlumaFileBrowserStore * model,
3500 GtkTreeIter * parent,
3501 GtkTreeIter * iter)
3502{
3503 GFile * file;
3504 FileBrowserNodeDir *parent_node;
3505 GError * error = NULL((void*)0);
3506 FileBrowserNode *node;
3507 gboolean result = FALSE(0);
3508
3509 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_269
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_269 = 1; else _g_boolean_var_269 =
0; _g_boolean_var_269; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
3510 g_return_val_if_fail (parent != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_270
; if (parent != ((void*)0)) _g_boolean_var_270 = 1; else _g_boolean_var_270
= 0; _g_boolean_var_270; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "parent != NULL")
; return ((0)); } } while (0)
;
3511 g_return_val_if_fail (parent->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_271
; if (parent->user_data != ((void*)0)) _g_boolean_var_271 =
1; else _g_boolean_var_271 = 0; _g_boolean_var_271; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "parent->user_data != NULL"); return ((0))
; } } while (0)
;
3512 g_return_val_if_fail (NODE_IS_DIRdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_272
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_272
= 1; else _g_boolean_var_272 = 0; _g_boolean_var_272; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
3513 ((FileBrowserNode *) (parent->user_data)),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_272
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_272
= 1; else _g_boolean_var_272 = 0; _g_boolean_var_272; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
3514 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_272
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_272
= 1; else _g_boolean_var_272 = 0; _g_boolean_var_272; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
;
3515 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_273
; if (iter != ((void*)0)) _g_boolean_var_273 = 1; else _g_boolean_var_273
= 0; _g_boolean_var_273; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
3516
3517 parent_node = FILE_BROWSER_NODE_DIR (parent->user_data)((FileBrowserNodeDir *)(parent->user_data));
3518 /* Translators: This is the default name of new directories created by the file browser pane. */
3519 file = unique_new_name (((FileBrowserNode *) parent_node)->file, _("directory")((char *) g_dgettext ("pluma", "directory")));
3520
3521 if (!g_file_make_directory (file, NULL((void*)0), &error)) {
3522 g_signal_emit (model, model_signals[ERROR], 0,
3523 PLUMA_FILE_BROWSER_ERROR_NEW_DIRECTORY,
3524 error->message);
3525 g_error_free (error);
3526 } else {
3527 node = model_add_node_from_file (model,
3528 (FileBrowserNode *)parent_node,
3529 file,
3530 NULL((void*)0));
3531
3532 if (model_node_visibility (model, node)) {
3533 iter->user_data = node;
3534 result = TRUE(!(0));
3535 } else {
3536 g_signal_emit (model, model_signals[ERROR], 0,
3537 PLUMA_FILE_BROWSER_ERROR_NEW_FILE,
3538 _((char *) g_dgettext ("pluma", "The new directory is currently filtered out. You need to adjust your filter settings to make the directory visible"
))
3539 ("The new directory is currently filtered out. You need to adjust your filter settings to make the directory visible")((char *) g_dgettext ("pluma", "The new directory is currently filtered out. You need to adjust your filter settings to make the directory visible"
))
);
3540 }
3541 }
3542
3543 g_object_unref (file);
3544 return result;
3545}
3546
3547void
3548_pluma_file_browser_store_register_type (GTypeModule *type_module)
3549{
3550 pluma_file_browser_store_register_type (type_module);
3551}
3552
3553// ex:ts=8:noet:
diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-7b3428.html b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-7b3428.html new file mode 100644 index 00000000..d6d8deae --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-7b3428.html @@ -0,0 +1,4233 @@ + + + +pluma-file-browser-store.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:plugins/filebrowser/pluma-file-browser-store.c
Warning:line 2059, column 8
Although the value stored to 'node' is used in the enclosing expression, the value is never actually read from 'node'
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pluma-file-browser-store.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/plugins/filebrowser -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I ../.. -I ../.. -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/gtksourceview-4 -I /usr/include/libpeas-1.0 -I /usr/include/gobject-introspection-1.0 -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/plugins/filebrowser -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-10-22-114445-13211-1 -x c pluma-file-browser-store.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * pluma-file-browser-store.c - Pluma plugin providing easy file access
3 * from the sidepanel
4 *
5 * Copyright (C) 2006 - Jesse van den Kieboom <jesse@icecrew.nl>
6 * Copyright (C) 2012-2021 MATE Developers
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23#ifdef HAVE_CONFIG_H1
24#include <config.h>
25#endif
26
27#include <string.h>
28#include <glib/gi18n-lib.h>
29#include <gio/gio.h>
30
31#include "pluma-file-browser-store.h"
32#include "pluma-file-browser-enum-types.h"
33#include "pluma-file-browser-error.h"
34#include "pluma-file-browser-utils.h"
35
36#define NODE_IS_DIR(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
(FILE_IS_DIR((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
)
)
37#define NODE_IS_HIDDEN(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
))
(FILE_IS_HIDDEN((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
)
)
38#define NODE_IS_TEXT(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_TEXT
))
(FILE_IS_TEXT((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_TEXT
)
)
39#define NODE_LOADED(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
(FILE_LOADED((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED))
40#define NODE_IS_FILTERED(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED
))
(FILE_IS_FILTERED((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED
)
)
41#define NODE_IS_DUMMY(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
(FILE_IS_DUMMY((node)->flags)((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
)
)
42
43#define FILE_BROWSER_NODE_DIR(node)((FileBrowserNodeDir *)(node)) ((FileBrowserNodeDir *)(node))
44
45#define DIRECTORY_LOAD_ITEMS_PER_CALLBACK100 100
46#define STANDARD_ATTRIBUTE_TYPES"standard::type" "," "standard::is-hidden" "," "standard::is-backup"
"," "standard::name" "," "standard::content-type" "," "standard::icon"
G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type" "," \
47 G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN"standard::is-hidden" "," \
48 G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP"standard::is-backup" "," \
49 G_FILE_ATTRIBUTE_STANDARD_NAME"standard::name" "," \
50 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE"standard::content-type" "," \
51 G_FILE_ATTRIBUTE_STANDARD_ICON"standard::icon"
52
53typedef struct _FileBrowserNode FileBrowserNode;
54typedef struct _FileBrowserNodeDir FileBrowserNodeDir;
55typedef struct _AsyncData AsyncData;
56typedef struct _AsyncNode AsyncNode;
57
58typedef gint (*SortFunc) (FileBrowserNode * node1,
59 FileBrowserNode * node2);
60
61struct _AsyncData
62{
63 PlumaFileBrowserStore * model;
64 GCancellable * cancellable;
65 gboolean trash;
66 GList * files;
67 GList * iter;
68 gboolean removed;
69};
70
71struct _AsyncNode
72{
73 FileBrowserNodeDir *dir;
74 GCancellable *cancellable;
75 GSList *original_children;
76};
77
78typedef struct {
79 PlumaFileBrowserStore * model;
80 gchar * virtual_root;
81 GMountOperation * operation;
82 GCancellable * cancellable;
83} MountInfo;
84
85struct _FileBrowserNode
86{
87 GFile *file;
88 guint flags;
89 gchar *name;
90
91 GdkPixbuf *icon;
92 GdkPixbuf *emblem;
93
94 FileBrowserNode *parent;
95 gint pos;
96 gboolean inserted;
97};
98
99struct _FileBrowserNodeDir
100{
101 FileBrowserNode node;
102 GSList *children;
103
104 GCancellable *cancellable;
105 GFileMonitor *monitor;
106 PlumaFileBrowserStore *model;
107};
108
109struct _PlumaFileBrowserStorePrivate
110{
111 FileBrowserNode *root;
112 FileBrowserNode *virtual_root;
113 GType column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_NUM];
114
115 PlumaFileBrowserStoreFilterMode filter_mode;
116 PlumaFileBrowserStoreFilterFunc filter_func;
117 gpointer filter_user_data;
118
119 SortFunc sort_func;
120
121 GSList *async_handles;
122 MountInfo *mount_info;
123};
124
125static FileBrowserNode *model_find_node (PlumaFileBrowserStore *model,
126 FileBrowserNode *node,
127 GFile *uri);
128static void model_remove_node (PlumaFileBrowserStore * model,
129 FileBrowserNode * node,
130 GtkTreePath * path,
131 gboolean free_nodes);
132
133static void set_virtual_root_from_node (PlumaFileBrowserStore * model,
134 FileBrowserNode * node);
135
136static void pluma_file_browser_store_iface_init (GtkTreeModelIface * iface);
137static GtkTreeModelFlags pluma_file_browser_store_get_flags (GtkTreeModel * tree_model);
138static gint pluma_file_browser_store_get_n_columns (GtkTreeModel * tree_model);
139static GType pluma_file_browser_store_get_column_type (GtkTreeModel * tree_model,
140 gint index);
141static gboolean pluma_file_browser_store_get_iter (GtkTreeModel * tree_model,
142 GtkTreeIter * iter,
143 GtkTreePath * path);
144static GtkTreePath *pluma_file_browser_store_get_path (GtkTreeModel * tree_model,
145 GtkTreeIter * iter);
146static void pluma_file_browser_store_get_value (GtkTreeModel * tree_model,
147 GtkTreeIter * iter,
148 gint column,
149 GValue * value);
150static gboolean pluma_file_browser_store_iter_next (GtkTreeModel * tree_model,
151 GtkTreeIter * iter);
152static gboolean pluma_file_browser_store_iter_children (GtkTreeModel * tree_model,
153 GtkTreeIter * iter,
154 GtkTreeIter * parent);
155static gboolean pluma_file_browser_store_iter_has_child (GtkTreeModel * tree_model,
156 GtkTreeIter * iter);
157static gint pluma_file_browser_store_iter_n_children (GtkTreeModel * tree_model,
158 GtkTreeIter * iter);
159static gboolean pluma_file_browser_store_iter_nth_child (GtkTreeModel * tree_model,
160 GtkTreeIter * iter,
161 GtkTreeIter * parent,
162 gint n);
163static gboolean pluma_file_browser_store_iter_parent (GtkTreeModel * tree_model,
164 GtkTreeIter * iter,
165 GtkTreeIter * child);
166static void pluma_file_browser_store_row_inserted (GtkTreeModel * tree_model,
167 GtkTreePath * path,
168 GtkTreeIter * iter);
169
170static void pluma_file_browser_store_drag_source_init (GtkTreeDragSourceIface * iface);
171static gboolean pluma_file_browser_store_row_draggable (GtkTreeDragSource * drag_source,
172 GtkTreePath * path);
173static gboolean pluma_file_browser_store_drag_data_delete (GtkTreeDragSource * drag_source,
174 GtkTreePath * path);
175static gboolean pluma_file_browser_store_drag_data_get (GtkTreeDragSource * drag_source,
176 GtkTreePath * path,
177 GtkSelectionData * selection_data);
178
179static void file_browser_node_free (PlumaFileBrowserStore * model,
180 FileBrowserNode * node);
181static void model_add_node (PlumaFileBrowserStore * model,
182 FileBrowserNode * child,
183 FileBrowserNode * parent);
184static void model_clear (PlumaFileBrowserStore * model,
185 gboolean free_nodes);
186static gint model_sort_default (FileBrowserNode * node1,
187 FileBrowserNode * node2);
188static void model_check_dummy (PlumaFileBrowserStore * model,
189 FileBrowserNode * node);
190static void next_files_async (GFileEnumerator * enumerator,
191 AsyncNode * async);
192
193static void delete_files (AsyncData *data);
194
195G_DEFINE_DYNAMIC_TYPE_EXTENDED (PlumaFileBrowserStore, pluma_file_browser_store,static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
196 G_TYPE_OBJECT,static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
197 0,static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
198 G_ADD_PRIVATE_DYNAMIC (PlumaFileBrowserStore)static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
199 G_IMPLEMENT_INTERFACE_DYNAMIC (GTK_TYPE_TREE_MODEL,static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
200 pluma_file_browser_store_iface_init)static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
201 G_IMPLEMENT_INTERFACE_DYNAMIC (GTK_TYPE_TREE_DRAG_SOURCE,static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
202 pluma_file_browser_store_drag_source_init))static void pluma_file_browser_store_init (PlumaFileBrowserStore
*self); static void pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass
*klass); static void pluma_file_browser_store_class_finalize
(PlumaFileBrowserStoreClass *klass); static gpointer pluma_file_browser_store_parent_class
= ((void*)0); static GType pluma_file_browser_store_type_id =
0; static gint PlumaFileBrowserStore_private_offset; static void
pluma_file_browser_store_class_intern_init (gpointer klass) {
pluma_file_browser_store_parent_class = g_type_class_peek_parent
(klass); if (PlumaFileBrowserStore_private_offset != 0) g_type_class_adjust_private_offset
(klass, &PlumaFileBrowserStore_private_offset); pluma_file_browser_store_class_init
((PlumaFileBrowserStoreClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer pluma_file_browser_store_get_instance_private
(PlumaFileBrowserStore *self) { return (((gpointer) ((guint8
*) (self) + (glong) (PlumaFileBrowserStore_private_offset))))
; } GType pluma_file_browser_store_get_type (void) { return pluma_file_browser_store_type_id
; } static void pluma_file_browser_store_register_type (GTypeModule
*type_module) { GType g_define_type_id __attribute__ ((__unused__
)); const GTypeInfo g_define_type_info = { sizeof (PlumaFileBrowserStoreClass
), (GBaseInitFunc) ((void*)0), (GBaseFinalizeFunc) ((void*)0)
, (GClassInitFunc)(void (*)(void)) pluma_file_browser_store_class_intern_init
, (GClassFinalizeFunc)(void (*)(void)) pluma_file_browser_store_class_finalize
, ((void*)0), sizeof (PlumaFileBrowserStore), 0, (GInstanceInitFunc
)(void (*)(void)) pluma_file_browser_store_init, ((void*)0) }
; pluma_file_browser_store_type_id = g_type_module_register_type
(type_module, ((GType) ((20) << (2))), "PlumaFileBrowserStore"
, &g_define_type_info, (GTypeFlags) 0); g_define_type_id =
pluma_file_browser_store_type_id; { { PlumaFileBrowserStore_private_offset
= sizeof (PlumaFileBrowserStorePrivate); } { const GInterfaceInfo
g_implement_interface_info = { (GInterfaceInitFunc)(void (*)
(void)) pluma_file_browser_store_iface_init, ((void*)0), ((void
*)0) }; g_type_module_add_interface (type_module, g_define_type_id
, (gtk_tree_model_get_type ()), &g_implement_interface_info
); } { const GInterfaceInfo g_implement_interface_info = { (GInterfaceInitFunc
)(void (*)(void)) pluma_file_browser_store_drag_source_init, (
(void*)0), ((void*)0) }; g_type_module_add_interface (type_module
, g_define_type_id, (gtk_tree_drag_source_get_type ()), &
g_implement_interface_info); } ; } }
203
204/* Properties */
205enum {
206 PROP_0,
207
208 PROP_ROOT,
209 PROP_VIRTUAL_ROOT,
210 PROP_FILTER_MODE
211};
212
213/* Signals */
214enum
215{
216 BEGIN_LOADING,
217 END_LOADING,
218 ERROR,
219 NO_TRASH,
220 RENAME,
221 BEGIN_REFRESH,
222 END_REFRESH,
223 UNLOAD,
224 NUM_SIGNALS
225};
226
227static guint model_signals[NUM_SIGNALS] = { 0 };
228
229static void
230cancel_mount_operation (PlumaFileBrowserStore *obj)
231{
232 if (obj->priv->mount_info != NULL((void*)0))
233 {
234 obj->priv->mount_info->model = NULL((void*)0);
235 g_cancellable_cancel (obj->priv->mount_info->cancellable);
236 obj->priv->mount_info = NULL((void*)0);
237 }
238}
239
240static void
241pluma_file_browser_store_finalize (GObject * object)
242{
243 PlumaFileBrowserStore *obj = PLUMA_FILE_BROWSER_STORE (object)((((PlumaFileBrowserStore*) (void *) ((object)))));
244 GSList *item;
245
246 /* Free all the nodes */
247 file_browser_node_free (obj, obj->priv->root);
248
249 /* Cancel any asynchronous operations */
250 for (item = obj->priv->async_handles; item; item = item->next)
251 {
252 AsyncData *data = (AsyncData *) (item->data);
253 g_cancellable_cancel (data->cancellable);
254
255 data->removed = TRUE(!(0));
256 }
257
258 cancel_mount_operation (obj);
259
260 g_slist_free (obj->priv->async_handles);
261 G_OBJECT_CLASS (pluma_file_browser_store_parent_class)((((GObjectClass*) (void *) ((pluma_file_browser_store_parent_class
)))))
->finalize (object);
262}
263
264static void
265set_gvalue_from_node (GValue *value,
266 FileBrowserNode *node)
267{
268 gchar * uri;
269
270 if (node == NULL((void*)0) || !node->file) {
271 g_value_set_string (value, NULL((void*)0));
272 } else {
273 uri = g_file_get_uri (node->file);
274 g_value_take_string (value, uri);
275 }
276}
277
278static void
279pluma_file_browser_store_get_property (GObject *object,
280 guint prop_id,
281 GValue *value,
282 GParamSpec *pspec)
283{
284 PlumaFileBrowserStore *obj = PLUMA_FILE_BROWSER_STORE (object)((((PlumaFileBrowserStore*) (void *) ((object)))));
285
286 switch (prop_id)
287 {
288 case PROP_ROOT:
289 set_gvalue_from_node (value, obj->priv->root);
290 break;
291 case PROP_VIRTUAL_ROOT:
292 set_gvalue_from_node (value, obj->priv->virtual_root);
293 break;
294 case PROP_FILTER_MODE:
295 g_value_set_flags (value, obj->priv->filter_mode);
296 break;
297 default:
298 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "pluma-file-browser-store.c", 298, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
299 break;
300 }
301}
302
303static void
304pluma_file_browser_store_set_property (GObject *object,
305 guint prop_id,
306 const GValue *value,
307 GParamSpec *pspec)
308{
309 PlumaFileBrowserStore *obj = PLUMA_FILE_BROWSER_STORE (object)((((PlumaFileBrowserStore*) (void *) ((object)))));
310
311 switch (prop_id)
312 {
313 case PROP_FILTER_MODE:
314 pluma_file_browser_store_set_filter_mode (obj,
315 g_value_get_flags (value));
316 break;
317 default:
318 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec
*_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id
= ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'"
, "pluma-file-browser-store.c", 318, ("property"), _glib__property_id
, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance
*) (_glib__pspec))->g_class))->g_type)))), (g_type_name
((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class
))->g_type)))))); } while (0)
;
319 break;
320 }
321}
322
323static void
324pluma_file_browser_store_class_init (PlumaFileBrowserStoreClass * klass)
325{
326 GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) ((klass)))));
327
328 object_class->finalize = pluma_file_browser_store_finalize;
329
330 object_class->get_property = pluma_file_browser_store_get_property;
331 object_class->set_property = pluma_file_browser_store_set_property;
332
333 g_object_class_install_property (object_class, PROP_ROOT,
334 g_param_spec_string ("root",
335 "Root",
336 "The root uri",
337 NULL((void*)0),
338 G_PARAM_READABLE));
339
340 g_object_class_install_property (object_class, PROP_VIRTUAL_ROOT,
341 g_param_spec_string ("virtual-root",
342 "Virtual Root",
343 "The virtual root uri",
344 NULL((void*)0),
345 G_PARAM_READABLE));
346
347 g_object_class_install_property (object_class, PROP_FILTER_MODE,
348 g_param_spec_flags ("filter-mode",
349 "Filter Mode",
350 "The filter mode",
351 PLUMA_TYPE_FILE_BROWSER_STORE_FILTER_MODE(pluma_file_browser_store_filter_mode_get_type()),
352 pluma_file_browser_store_filter_mode_get_default (),
353 G_PARAM_READWRITE));
354
355 model_signals[BEGIN_LOADING] =
356 g_signal_new ("begin-loading",
357 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
358 G_SIGNAL_RUN_LAST,
359 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, begin_loading)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, begin_loading
))
,
360 NULL((void*)0), NULL((void*)0), NULL((void*)0),
361 G_TYPE_NONE((GType) ((1) << (2))), 1, GTK_TYPE_TREE_ITER(gtk_tree_iter_get_type ()));
362 model_signals[END_LOADING] =
363 g_signal_new ("end-loading",
364 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
365 G_SIGNAL_RUN_LAST,
366 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, end_loading)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, end_loading
))
,
367 NULL((void*)0), NULL((void*)0), NULL((void*)0),
368 G_TYPE_NONE((GType) ((1) << (2))), 1,
369 GTK_TYPE_TREE_ITER(gtk_tree_iter_get_type ()));
370 model_signals[ERROR] =
371 g_signal_new ("error", G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
372 G_SIGNAL_RUN_LAST,
373 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, error)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, error
))
,
374 NULL((void*)0), NULL((void*)0), NULL((void*)0),
375 G_TYPE_NONE((GType) ((1) << (2))), 2, G_TYPE_UINT((GType) ((7) << (2))), G_TYPE_STRING((GType) ((16) << (2))));
376 model_signals[NO_TRASH] =
377 g_signal_new ("no-trash", G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
378 G_SIGNAL_RUN_LAST,
379 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, no_trash)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, no_trash
))
,
380 g_signal_accumulator_true_handled, NULL((void*)0), NULL((void*)0),
381 G_TYPE_BOOLEAN((GType) ((5) << (2))), 1, G_TYPE_POINTER((GType) ((17) << (2))));
382 model_signals[RENAME] =
383 g_signal_new ("rename",
384 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
385 G_SIGNAL_RUN_LAST,
386 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, rename)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, rename
))
,
387 NULL((void*)0), NULL((void*)0), NULL((void*)0),
388 G_TYPE_NONE((GType) ((1) << (2))), 2,
389 G_TYPE_STRING((GType) ((16) << (2))),
390 G_TYPE_STRING((GType) ((16) << (2))));
391 model_signals[BEGIN_REFRESH] =
392 g_signal_new ("begin-refresh",
393 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
394 G_SIGNAL_RUN_LAST,
395 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, begin_refresh)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, begin_refresh
))
,
396 NULL((void*)0), NULL((void*)0), NULL((void*)0),
397 G_TYPE_NONE((GType) ((1) << (2))), 0);
398 model_signals[END_REFRESH] =
399 g_signal_new ("end-refresh",
400 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
401 G_SIGNAL_RUN_LAST,
402 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, end_refresh)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, end_refresh
))
,
403 NULL((void*)0), NULL((void*)0), NULL((void*)0),
404 G_TYPE_NONE((GType) ((1) << (2))), 0);
405 model_signals[UNLOAD] =
406 g_signal_new ("unload",
407 G_OBJECT_CLASS_TYPE (object_class)((((GTypeClass*) (object_class))->g_type)),
408 G_SIGNAL_RUN_LAST,
409 G_STRUCT_OFFSET (PlumaFileBrowserStoreClass, unload)((glong) __builtin_offsetof(PlumaFileBrowserStoreClass, unload
))
,
410 NULL((void*)0), NULL((void*)0), NULL((void*)0),
411 G_TYPE_NONE((GType) ((1) << (2))), 1,
412 G_TYPE_STRING((GType) ((16) << (2))));
413}
414
415static void
416pluma_file_browser_store_class_finalize (PlumaFileBrowserStoreClass *klass)
417{
418 /* dummy function - used by G_DEFINE_DYNAMIC_TYPE_EXTENDED */
419}
420
421static void
422pluma_file_browser_store_iface_init (GtkTreeModelIface * iface)
423{
424 iface->get_flags = pluma_file_browser_store_get_flags;
425 iface->get_n_columns = pluma_file_browser_store_get_n_columns;
426 iface->get_column_type = pluma_file_browser_store_get_column_type;
427 iface->get_iter = pluma_file_browser_store_get_iter;
428 iface->get_path = pluma_file_browser_store_get_path;
429 iface->get_value = pluma_file_browser_store_get_value;
430 iface->iter_next = pluma_file_browser_store_iter_next;
431 iface->iter_children = pluma_file_browser_store_iter_children;
432 iface->iter_has_child = pluma_file_browser_store_iter_has_child;
433 iface->iter_n_children = pluma_file_browser_store_iter_n_children;
434 iface->iter_nth_child = pluma_file_browser_store_iter_nth_child;
435 iface->iter_parent = pluma_file_browser_store_iter_parent;
436 iface->row_inserted = pluma_file_browser_store_row_inserted;
437}
438
439static void
440pluma_file_browser_store_drag_source_init (GtkTreeDragSourceIface * iface)
441{
442 iface->row_draggable = pluma_file_browser_store_row_draggable;
443 iface->drag_data_delete = pluma_file_browser_store_drag_data_delete;
444 iface->drag_data_get = pluma_file_browser_store_drag_data_get;
445}
446
447static void
448pluma_file_browser_store_init (PlumaFileBrowserStore * obj)
449{
450 obj->priv = pluma_file_browser_store_get_instance_private (obj);
451
452 obj->priv->column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_URI] =
453 G_TYPE_STRING((GType) ((16) << (2)));
454 obj->priv->column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_NAME] =
455 G_TYPE_STRING((GType) ((16) << (2)));
456 obj->priv->column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_FLAGS] =
457 G_TYPE_UINT((GType) ((7) << (2)));
458 obj->priv->column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_ICON] =
459 GDK_TYPE_PIXBUF(gdk_pixbuf_get_type ());
460 obj->priv->column_types[PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM] =
461 GDK_TYPE_PIXBUF(gdk_pixbuf_get_type ());
462
463 // Default filter mode is hiding the hidden files
464 obj->priv->filter_mode = pluma_file_browser_store_filter_mode_get_default ();
465 obj->priv->sort_func = model_sort_default;
466}
467
468static gboolean
469node_has_parent (FileBrowserNode * node, FileBrowserNode * parent)
470{
471 if (node->parent == NULL((void*)0))
472 return FALSE(0);
473
474 if (node->parent == parent)
475 return TRUE(!(0));
476
477 return node_has_parent (node->parent, parent);
478}
479
480static gboolean
481node_in_tree (PlumaFileBrowserStore * model, FileBrowserNode * node)
482{
483 return node_has_parent (node, model->priv->virtual_root);
484}
485
486static gboolean
487model_node_visibility (PlumaFileBrowserStore * model,
488 FileBrowserNode * node)
489{
490 if (node == NULL((void*)0))
491 return FALSE(0);
492
493 if (NODE_IS_DUMMY (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
)
494 return !NODE_IS_HIDDEN (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
))
;
495
496 if (node == model->priv->virtual_root)
497 return TRUE(!(0));
498
499 if (!node_has_parent (node, model->priv->virtual_root))
500 return FALSE(0);
501
502 return !NODE_IS_FILTERED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED
))
;
503}
504
505static gboolean
506model_node_inserted (PlumaFileBrowserStore * model,
507 FileBrowserNode * node)
508{
509 return node == model->priv->virtual_root || (model_node_visibility (model, node) && node->inserted);
510}
511
512/* Interface implementation */
513
514static GtkTreeModelFlags
515pluma_file_browser_store_get_flags (GtkTreeModel * tree_model)
516{
517 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_274
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_274 = 1; else _g_boolean_var_274 =
0; _g_boolean_var_274; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((GtkTreeModelFlags) 0); } } while (0)
518 (GtkTreeModelFlags) 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_274
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_274 = 1; else _g_boolean_var_274 =
0; _g_boolean_var_274; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((GtkTreeModelFlags) 0); } } while (0)
;
519
520 return GTK_TREE_MODEL_ITERS_PERSIST;
521}
522
523static gint
524pluma_file_browser_store_get_n_columns (GtkTreeModel * tree_model)
525{
526 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model), 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_275
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_275 = 1; else _g_boolean_var_275 =
0; _g_boolean_var_275; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return (0); } } while (0)
;
527
528 return PLUMA_FILE_BROWSER_STORE_COLUMN_NUM;
529}
530
531static GType
532pluma_file_browser_store_get_column_type (GtkTreeModel * tree_model, gint idx)
533{
534 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_276
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_276 = 1; else _g_boolean_var_276 =
0; _g_boolean_var_276; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return (((GType) ((0) << (2)))); } } while (0)
535 G_TYPE_INVALID)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_276
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_276 = 1; else _g_boolean_var_276 =
0; _g_boolean_var_276; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return (((GType) ((0) << (2)))); } } while (0)
;
536 g_return_val_if_fail (idx < PLUMA_FILE_BROWSER_STORE_COLUMN_NUM &&do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_277
; if (idx < PLUMA_FILE_BROWSER_STORE_COLUMN_NUM &&
idx >= 0) _g_boolean_var_277 = 1; else _g_boolean_var_277
= 0; _g_boolean_var_277; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "idx < PLUMA_FILE_BROWSER_STORE_COLUMN_NUM && idx >= 0"
); return (((GType) ((0) << (2)))); } } while (0)
537 idx >= 0, G_TYPE_INVALID)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_277
; if (idx < PLUMA_FILE_BROWSER_STORE_COLUMN_NUM &&
idx >= 0) _g_boolean_var_277 = 1; else _g_boolean_var_277
= 0; _g_boolean_var_277; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "idx < PLUMA_FILE_BROWSER_STORE_COLUMN_NUM && idx >= 0"
); return (((GType) ((0) << (2)))); } } while (0)
;
538
539 return PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))))->priv->column_types[idx];
540}
541
542static gboolean
543pluma_file_browser_store_get_iter (GtkTreeModel * tree_model,
544 GtkTreeIter * iter, GtkTreePath * path)
545{
546 gint * indices, depth, i;
547 FileBrowserNode * node;
548 PlumaFileBrowserStore * model;
549 gint num;
550
551 g_assert (PLUMA_IS_FILE_BROWSER_STORE (tree_model))do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_278
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_278 = 1; else _g_boolean_var_278 =
0; _g_boolean_var_278; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "pluma-file-browser-store.c", 551, ((const char
*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"); }
while (0)
;
552 g_assert (path != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_279
; if (path != ((void*)0)) _g_boolean_var_279 = 1; else _g_boolean_var_279
= 0; _g_boolean_var_279; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "pluma-file-browser-store.c", 552, ((const char
*) (__func__)), "path != NULL"); } while (0)
;
553
554 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
555 indices = gtk_tree_path_get_indices (path);
556 depth = gtk_tree_path_get_depth (path);
557 node = model->priv->virtual_root;
558
559 for (i = 0; i < depth; ++i) {
560 GSList * item;
561
562 if (node == NULL((void*)0))
563 return FALSE(0);
564
565 num = 0;
566
567 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
568 return FALSE(0);
569
570 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item; item = item->next) {
571 FileBrowserNode * child;
572
573 child = (FileBrowserNode *) (item->data);
574
575 if (model_node_inserted (model, child)) {
576 if (num == indices[i]) {
577 node = child;
578 break;
579 }
580
581 num++;
582 }
583 }
584
585 if (item == NULL((void*)0))
586 return FALSE(0);
587
588 node = (FileBrowserNode *) (item->data);
589 }
590
591 iter->user_data = node;
592 iter->user_data2 = NULL((void*)0);
593 iter->user_data3 = NULL((void*)0);
594
595 return node != NULL((void*)0);
596}
597
598static GtkTreePath *
599pluma_file_browser_store_get_path_real (PlumaFileBrowserStore * model,
600 FileBrowserNode * node)
601{
602 GtkTreePath *path;
603 gint num = 0;
604
605 path = gtk_tree_path_new ();
606
607 while (node != model->priv->virtual_root) {
608 GSList *item;
609
610 if (node->parent == NULL((void*)0)) {
611 gtk_tree_path_free (path);
612 return NULL((void*)0);
613 }
614
615 num = 0;
616
617 for (item = FILE_BROWSER_NODE_DIR (node->parent)((FileBrowserNodeDir *)(node->parent))->children; item; item = item->next) {
618 FileBrowserNode *check;
619
620 check = (FileBrowserNode *) (item->data);
621
622 if (model_node_visibility (model, check) && (check == node || check->inserted)) {
623 if (check == node) {
624 gtk_tree_path_prepend_index (path,
625 num);
626 break;
627 }
628
629 ++num;
630 } else if (check == node) {
631 if (NODE_IS_DUMMY (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
)
632 g_warning ("Dummy not visible???");
633
634 gtk_tree_path_free (path);
635 return NULL((void*)0);
636 }
637 }
638
639 node = node->parent;
640 }
641
642 return path;
643}
644
645static GtkTreePath *
646pluma_file_browser_store_get_path (GtkTreeModel * tree_model,
647 GtkTreeIter * iter)
648{
649 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_280
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_280 = 1; else _g_boolean_var_280 =
0; _g_boolean_var_280; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return (((void*)0)); } } while (0)
;
650 g_return_val_if_fail (iter != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_281
; if (iter != ((void*)0)) _g_boolean_var_281 = 1; else _g_boolean_var_281
= 0; _g_boolean_var_281; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
(((void*)0)); } } while (0)
;
651 g_return_val_if_fail (iter->user_data != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_282
; if (iter->user_data != ((void*)0)) _g_boolean_var_282 = 1
; else _g_boolean_var_282 = 0; _g_boolean_var_282; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return (((void
*)0)); } } while (0)
;
652
653 return pluma_file_browser_store_get_path_real (PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model))))),
654 (FileBrowserNode *) (iter->user_data));
655}
656
657static void
658pluma_file_browser_store_get_value (GtkTreeModel * tree_model,
659 GtkTreeIter * iter,
660 gint column,
661 GValue * value)
662{
663 FileBrowserNode *node;
664
665 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_283
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_283 = 1; else _g_boolean_var_283 =
0; _g_boolean_var_283; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return; } } while (0)
;
666 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_284
; if (iter != ((void*)0)) _g_boolean_var_284 = 1; else _g_boolean_var_284
= 0; _g_boolean_var_284; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
667 g_return_if_fail (iter->user_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_285
; if (iter->user_data != ((void*)0)) _g_boolean_var_285 = 1
; else _g_boolean_var_285 = 0; _g_boolean_var_285; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return; } } while
(0)
;
668
669 node = (FileBrowserNode *) (iter->user_data);
670
671 g_value_init (value, PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))))->priv->column_types[column]);
672
673 switch (column) {
674 case PLUMA_FILE_BROWSER_STORE_COLUMN_URI:
675 set_gvalue_from_node (value, node);
676 break;
677 case PLUMA_FILE_BROWSER_STORE_COLUMN_NAME:
678 g_value_set_string (value, node->name);
679 break;
680 case PLUMA_FILE_BROWSER_STORE_COLUMN_FLAGS:
681 g_value_set_uint (value, node->flags);
682 break;
683 case PLUMA_FILE_BROWSER_STORE_COLUMN_ICON:
684 g_value_set_object (value, node->icon);
685 break;
686 case PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM:
687 g_value_set_object (value, node->emblem);
688 break;
689 default:
690 g_return_if_reached ()do { g_log (((gchar*) 0), G_LOG_LEVEL_CRITICAL, "file %s: line %d (%s): should not be reached"
, "pluma-file-browser-store.c", 690, ((const char*) (__func__
))); return; } while (0)
;
691 }
692}
693
694static gboolean
695pluma_file_browser_store_iter_next (GtkTreeModel * tree_model,
696 GtkTreeIter * iter)
697{
698 PlumaFileBrowserStore * model;
699 FileBrowserNode * node;
700 GSList * item;
701 GSList * first;
702
703 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_286
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_286 = 1; else _g_boolean_var_286 =
0; _g_boolean_var_286; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
704 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_286
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_286 = 1; else _g_boolean_var_286 =
0; _g_boolean_var_286; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
705 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_287
; if (iter != ((void*)0)) _g_boolean_var_287 = 1; else _g_boolean_var_287
= 0; _g_boolean_var_287; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
706 g_return_val_if_fail (iter->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_288
; if (iter->user_data != ((void*)0)) _g_boolean_var_288 = 1
; else _g_boolean_var_288 = 0; _g_boolean_var_288; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return ((0)); }
} while (0)
;
707
708 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
709 node = (FileBrowserNode *) (iter->user_data);
710
711 if (node->parent == NULL((void*)0))
712 return FALSE(0);
713
714 first = g_slist_next (g_slist_find (FILE_BROWSER_NODE_DIR (node->parent)->children, node))((g_slist_find (((FileBrowserNodeDir *)(node->parent))->
children, node)) ? (((GSList *)(g_slist_find (((FileBrowserNodeDir
*)(node->parent))->children, node)))->next) : ((void
*)0))
;
715
716 for (item = first; item; item = item->next) {
717 if (model_node_inserted (model, (FileBrowserNode *) (item->data))) {
718 iter->user_data = item->data;
719 return TRUE(!(0));
720 }
721 }
722
723 return FALSE(0);
724}
725
726static gboolean
727pluma_file_browser_store_iter_children (GtkTreeModel * tree_model,
728 GtkTreeIter * iter,
729 GtkTreeIter * parent)
730{
731 FileBrowserNode * node;
732 PlumaFileBrowserStore * model;
733 GSList * item;
734
735 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_289
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_289 = 1; else _g_boolean_var_289 =
0; _g_boolean_var_289; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
736 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_289
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_289 = 1; else _g_boolean_var_289 =
0; _g_boolean_var_289; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
737 g_return_val_if_fail (parent == NULLdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_290
; if (parent == ((void*)0) || parent->user_data != ((void*
)0)) _g_boolean_var_290 = 1; else _g_boolean_var_290 = 0; _g_boolean_var_290
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "parent == NULL || parent->user_data != NULL"
); return ((0)); } } while (0)
738 || parent->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_290
; if (parent == ((void*)0) || parent->user_data != ((void*
)0)) _g_boolean_var_290 = 1; else _g_boolean_var_290 = 0; _g_boolean_var_290
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "parent == NULL || parent->user_data != NULL"
); return ((0)); } } while (0)
;
739
740 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
741
742 if (parent == NULL((void*)0))
743 node = model->priv->virtual_root;
744 else
745 node = (FileBrowserNode *) (parent->user_data);
746
747 if (node == NULL((void*)0))
748 return FALSE(0);
749
750 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
751 return FALSE(0);
752
753 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item; item = item->next) {
754 if (model_node_inserted (model, (FileBrowserNode *) (item->data))) {
755 iter->user_data = item->data;
756 return TRUE(!(0));
757 }
758 }
759
760 return FALSE(0);
761}
762
763static gboolean
764filter_tree_model_iter_has_child_real (PlumaFileBrowserStore * model,
765 FileBrowserNode * node)
766{
767 GSList *item;
768
769 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
770 return FALSE(0);
771
772 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item; item = item->next) {
773 if (model_node_inserted (model, (FileBrowserNode *) (item->data)))
774 return TRUE(!(0));
775 }
776
777 return FALSE(0);
778}
779
780static gboolean
781pluma_file_browser_store_iter_has_child (GtkTreeModel * tree_model,
782 GtkTreeIter * iter)
783{
784 FileBrowserNode *node;
785 PlumaFileBrowserStore *model;
786
787 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_291
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_291 = 1; else _g_boolean_var_291 =
0; _g_boolean_var_291; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
788 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_291
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_291 = 1; else _g_boolean_var_291 =
0; _g_boolean_var_291; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
789 g_return_val_if_fail (iter == NULLdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_292
; if (iter == ((void*)0) || iter->user_data != ((void*)0))
_g_boolean_var_292 = 1; else _g_boolean_var_292 = 0; _g_boolean_var_292
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "iter == NULL || iter->user_data != NULL"
); return ((0)); } } while (0)
790 || iter->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_292
; if (iter == ((void*)0) || iter->user_data != ((void*)0))
_g_boolean_var_292 = 1; else _g_boolean_var_292 = 0; _g_boolean_var_292
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "iter == NULL || iter->user_data != NULL"
); return ((0)); } } while (0)
;
791
792 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
793
794 if (iter == NULL((void*)0))
795 node = model->priv->virtual_root;
796 else
797 node = (FileBrowserNode *) (iter->user_data);
798
799 return filter_tree_model_iter_has_child_real (model, node);
800}
801
802static gint
803pluma_file_browser_store_iter_n_children (GtkTreeModel * tree_model,
804 GtkTreeIter * iter)
805{
806 FileBrowserNode *node;
807 PlumaFileBrowserStore *model;
808 GSList *item;
809 gint num = 0;
810
811 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_293
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_293 = 1; else _g_boolean_var_293 =
0; _g_boolean_var_293; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
812 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_293
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_293 = 1; else _g_boolean_var_293 =
0; _g_boolean_var_293; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
813 g_return_val_if_fail (iter == NULLdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_294
; if (iter == ((void*)0) || iter->user_data != ((void*)0))
_g_boolean_var_294 = 1; else _g_boolean_var_294 = 0; _g_boolean_var_294
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "iter == NULL || iter->user_data != NULL"
); return ((0)); } } while (0)
814 || iter->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_294
; if (iter == ((void*)0) || iter->user_data != ((void*)0))
_g_boolean_var_294 = 1; else _g_boolean_var_294 = 0; _g_boolean_var_294
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "iter == NULL || iter->user_data != NULL"
); return ((0)); } } while (0)
;
815
816 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
817
818 if (iter == NULL((void*)0))
819 node = model->priv->virtual_root;
820 else
821 node = (FileBrowserNode *) (iter->user_data);
822
823 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
824 return 0;
825
826 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item; item = item->next)
827 if (model_node_inserted (model, (FileBrowserNode *) (item->data)))
828 ++num;
829
830 return num;
831}
832
833static gboolean
834pluma_file_browser_store_iter_nth_child (GtkTreeModel * tree_model,
835 GtkTreeIter * iter,
836 GtkTreeIter * parent, gint n)
837{
838 FileBrowserNode *node;
839 PlumaFileBrowserStore *model;
840 GSList *item;
841 gint num = 0;
842
843 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_295
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_295 = 1; else _g_boolean_var_295 =
0; _g_boolean_var_295; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
844 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_295
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_295 = 1; else _g_boolean_var_295 =
0; _g_boolean_var_295; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
845 g_return_val_if_fail (parent == NULLdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_296
; if (parent == ((void*)0) || parent->user_data != ((void*
)0)) _g_boolean_var_296 = 1; else _g_boolean_var_296 = 0; _g_boolean_var_296
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "parent == NULL || parent->user_data != NULL"
); return ((0)); } } while (0)
846 || parent->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_296
; if (parent == ((void*)0) || parent->user_data != ((void*
)0)) _g_boolean_var_296 = 1; else _g_boolean_var_296 = 0; _g_boolean_var_296
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "parent == NULL || parent->user_data != NULL"
); return ((0)); } } while (0)
;
847
848 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
849
850 if (parent == NULL((void*)0))
851 node = model->priv->virtual_root;
852 else
853 node = (FileBrowserNode *) (parent->user_data);
854
855 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
856 return FALSE(0);
857
858 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item;
859 item = item->next) {
860 if (model_node_inserted (model, (FileBrowserNode *) (item->data))) {
861 if (num == n) {
862 iter->user_data = item->data;
863 return TRUE(!(0));
864 }
865
866 ++num;
867 }
868 }
869
870 return FALSE(0);
871}
872
873static gboolean
874pluma_file_browser_store_iter_parent (GtkTreeModel * tree_model,
875 GtkTreeIter * iter,
876 GtkTreeIter * child)
877{
878 FileBrowserNode *node;
879 PlumaFileBrowserStore *model;
880
881 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_297
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_297 = 1; else _g_boolean_var_297 =
0; _g_boolean_var_297; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return ((0)); } } while (0)
;
882 g_return_val_if_fail (child != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_298
; if (child != ((void*)0)) _g_boolean_var_298 = 1; else _g_boolean_var_298
= 0; _g_boolean_var_298; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "child != NULL");
return ((0)); } } while (0)
;
883 g_return_val_if_fail (child->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_299
; if (child->user_data != ((void*)0)) _g_boolean_var_299 =
1; else _g_boolean_var_299 = 0; _g_boolean_var_299; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "child->user_data != NULL"); return ((0));
} } while (0)
;
884
885 node = (FileBrowserNode *) (child->user_data);
886 model = PLUMA_FILE_BROWSER_STORE (tree_model)((((PlumaFileBrowserStore*) (void *) ((tree_model)))));
887
888 if (!node_in_tree (model, node))
889 return FALSE(0);
890
891 if (node->parent == NULL((void*)0))
892 return FALSE(0);
893
894 iter->user_data = node->parent;
895 return TRUE(!(0));
896}
897
898static void
899pluma_file_browser_store_row_inserted (GtkTreeModel * tree_model,
900 GtkTreePath * path,
901 GtkTreeIter * iter)
902{
903 FileBrowserNode * node = (FileBrowserNode *)(iter->user_data);
904
905 node->inserted = TRUE(!(0));
906}
907
908static gboolean
909pluma_file_browser_store_row_draggable (GtkTreeDragSource * drag_source,
910 GtkTreePath * path)
911{
912 GtkTreeIter iter;
913 PlumaFileBrowserStoreFlag flags;
914
915 if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source)((((GtkTreeModel*) (void *) ((drag_source))))),
916 &iter, path))
917 {
918 return FALSE(0);
919 }
920
921 gtk_tree_model_get (GTK_TREE_MODEL (drag_source)((((GtkTreeModel*) (void *) ((drag_source))))), &iter,
922 PLUMA_FILE_BROWSER_STORE_COLUMN_FLAGS, &flags,
923 -1);
924
925 return !FILE_IS_DUMMY(flags)(flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY);
926}
927
928static gboolean
929pluma_file_browser_store_drag_data_delete (GtkTreeDragSource * drag_source,
930 GtkTreePath * path)
931{
932 return FALSE(0);
933}
934
935static gboolean
936pluma_file_browser_store_drag_data_get (GtkTreeDragSource * drag_source,
937 GtkTreePath * path,
938 GtkSelectionData * selection_data)
939{
940 GtkTreeIter iter;
941 gchar *uri;
942 gchar *uris[2] = {0, };
943 gboolean ret;
944
945 if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source)((((GtkTreeModel*) (void *) ((drag_source))))),
946 &iter, path))
947 {
948 return FALSE(0);
949 }
950
951 gtk_tree_model_get (GTK_TREE_MODEL (drag_source)((((GtkTreeModel*) (void *) ((drag_source))))), &iter,
952 PLUMA_FILE_BROWSER_STORE_COLUMN_URI, &uri,
953 -1);
954
955 g_assert (uri)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_300
; if (uri) _g_boolean_var_300 = 1; else _g_boolean_var_300 = 0
; _g_boolean_var_300; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "pluma-file-browser-store.c", 955, ((const char
*) (__func__)), "uri"); } while (0)
;
956
957 uris[0] = uri;
958 ret = gtk_selection_data_set_uris (selection_data, uris);
959
960 g_free (uri);
961
962 return ret;
963}
964
965#define FILTER_HIDDEN(mode)(mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_HIDDEN) (mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_HIDDEN)
966#define FILTER_BINARY(mode)(mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_BINARY) (mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_BINARY)
967
968/* Private */
969static void
970model_begin_loading (PlumaFileBrowserStore * model, FileBrowserNode * node)
971{
972 GtkTreeIter iter;
973
974 iter.user_data = node;
975 g_signal_emit (model, model_signals[BEGIN_LOADING], 0, &iter);
976}
977
978static void
979model_end_loading (PlumaFileBrowserStore * model, FileBrowserNode * node)
980{
981 GtkTreeIter iter;
982
983 iter.user_data = node;
984 g_signal_emit (model, model_signals[END_LOADING], 0, &iter);
985}
986
987static void
988model_node_update_visibility (PlumaFileBrowserStore * model,
989 FileBrowserNode * node)
990{
991 GtkTreeIter iter;
992
993 node->flags &= ~PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED;
994
995 if (FILTER_HIDDEN (model->priv->filter_mode)(model->priv->filter_mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_HIDDEN
)
&&
996 NODE_IS_HIDDEN (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
))
)
997 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED;
998 else if (FILTER_BINARY (model->priv->filter_mode)(model->priv->filter_mode & PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_BINARY
)
&&
999 (!NODE_IS_TEXT (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_TEXT
))
&& !NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
))
1000 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED;
1001 else if (model->priv->filter_func) {
1002 iter.user_data = node;
1003
1004 if (!model->priv->
1005 filter_func (model, &iter,
1006 model->priv->filter_user_data))
1007 node->flags |=
1008 PLUMA_FILE_BROWSER_STORE_FLAG_IS_FILTERED;
1009 }
1010}
1011
1012static gint
1013collate_nodes (FileBrowserNode * node1, FileBrowserNode * node2)
1014{
1015 if (node1->name == NULL((void*)0))
1016 return -1;
1017 else if (node2->name == NULL((void*)0))
1018 return 1;
1019 else {
1020 gchar *k1, *k2;
1021 gint result;
1022
1023 k1 = g_utf8_collate_key_for_filename (node1->name, -1);
1024 k2 = g_utf8_collate_key_for_filename (node2->name, -1);
1025
1026 result = strcmp (k1, k2);
1027
1028 g_free (k1);
1029 g_free (k2);
1030
1031 return result;
1032 }
1033}
1034
1035static gint
1036model_sort_default (FileBrowserNode * node1, FileBrowserNode * node2)
1037{
1038 gint f1;
1039 gint f2;
1040
1041 f1 = NODE_IS_DUMMY (node1)(((node1)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
;
1042 f2 = NODE_IS_DUMMY (node2)(((node2)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
;
1043
1044 if (f1 && f2)
1045 {
1046 return 0;
1047 }
1048 else if (f1 || f2)
1049 {
1050 return f1 ? -1 : 1;
1051 }
1052
1053 f1 = NODE_IS_DIR (node1)(((node1)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
;
1054 f2 = NODE_IS_DIR (node2)(((node2)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
;
1055
1056 if (f1 != f2)
1057 {
1058 return f1 ? -1 : 1;
1059 }
1060
1061 f1 = NODE_IS_HIDDEN (node1)(((node1)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
))
;
1062 f2 = NODE_IS_HIDDEN (node2)(((node2)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN
))
;
1063
1064 if (f1 != f2)
1065 {
1066 return f2 ? -1 : 1;
1067 }
1068
1069 return collate_nodes (node1, node2);
1070}
1071
1072static void
1073model_resort_node (PlumaFileBrowserStore * model, FileBrowserNode * node)
1074{
1075 FileBrowserNodeDir *dir;
1076 GSList *item;
1077 FileBrowserNode *child;
1078 gint pos = 0;
1079 GtkTreeIter iter;
1080 GtkTreePath *path;
1081 gint *neworder;
1082
1083 dir = FILE_BROWSER_NODE_DIR (node->parent)((FileBrowserNodeDir *)(node->parent));
1084
1085 if (!model_node_visibility (model, node->parent)) {
1086 /* Just sort the children of the parent */
1087 dir->children = g_slist_sort (dir->children,
1088 (GCompareFunc) (model->priv->
1089 sort_func));
1090 } else {
1091 /* Store current positions */
1092 for (item = dir->children; item; item = item->next) {
1093 child = (FileBrowserNode *) (item->data);
1094
1095 if (model_node_visibility (model, child))
1096 child->pos = pos++;
1097 }
1098
1099 dir->children = g_slist_sort (dir->children,
1100 (GCompareFunc) (model->priv->
1101 sort_func));
1102 neworder = g_new (gint, pos)(gint *) (__extension__ ({ gsize __n = (gsize) (pos); gsize __s
= sizeof (gint); gpointer __p; if (__s == 1) __p = g_malloc (
__n); else if (__builtin_constant_p (__n) && (__s == 0
|| __n <= (9223372036854775807L *2UL+1UL) / __s)) __p = g_malloc
(__n * __s); else __p = g_malloc_n (__n, __s); __p; }))
;
1103 pos = 0;
1104
1105 /* Store the new positions */
1106 for (item = dir->children; item; item = item->next) {
1107 child = (FileBrowserNode *) (item->data);
1108
1109 if (model_node_visibility (model, child))
1110 neworder[pos++] = child->pos;
1111 }
1112
1113 iter.user_data = node->parent;
1114 path =
1115 pluma_file_browser_store_get_path_real (model,
1116 node->parent);
1117
1118 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (model)((((GtkTreeModel*) (void *) ((model))))),
1119 path, &iter, neworder);
1120
1121 g_free (neworder);
1122 gtk_tree_path_free (path);
1123 }
1124}
1125
1126static void
1127row_changed (PlumaFileBrowserStore * model,
1128 GtkTreePath ** path,
1129 GtkTreeIter * iter)
1130{
1131 GtkTreeRowReference *ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (model)((((GtkTreeModel*) (void *) ((model))))), *path);
1132
1133 /* Insert a copy of the actual path here because the row-inserted
1134 signal may alter the path */
1135 gtk_tree_model_row_changed (GTK_TREE_MODEL(model)((((GtkTreeModel*) (void *) ((model))))), *path, iter);
1136 gtk_tree_path_free (*path);
1137
1138 *path = gtk_tree_row_reference_get_path (ref);
1139 gtk_tree_row_reference_free (ref);
1140}
1141
1142static void
1143row_inserted (PlumaFileBrowserStore * model,
1144 GtkTreePath ** path,
1145 GtkTreeIter * iter)
1146{
1147 /* This function creates a row reference for the path because it's
1148 uncertain what might change the actual model/view when we insert
1149 a node, maybe another directory load is triggered for example.
1150 Because functions that use this function rely on the notion that
1151 the path remains pointed towards the inserted node, we use the
1152 reference to keep track. */
1153 GtkTreeRowReference *ref = gtk_tree_row_reference_new (GTK_TREE_MODEL (model)((((GtkTreeModel*) (void *) ((model))))), *path);
1154 GtkTreePath * copy = gtk_tree_path_copy (*path);
1155
1156 gtk_tree_model_row_inserted (GTK_TREE_MODEL(model)((((GtkTreeModel*) (void *) ((model))))), copy, iter);
1157 gtk_tree_path_free (copy);
1158
1159 if (ref)
1160 {
1161 gtk_tree_path_free (*path);
1162
1163 /* To restore the path, we get the path from the reference. But, since
1164 we inserted a row, the path will be one index further than the
1165 actual path of our node. We therefore call gtk_tree_path_prev */
1166 *path = gtk_tree_row_reference_get_path (ref);
1167 gtk_tree_path_prev (*path);
1168 }
1169
1170 gtk_tree_row_reference_free (ref);
1171}
1172
1173static void
1174row_deleted (PlumaFileBrowserStore * model,
1175 const GtkTreePath * path)
1176{
1177 GtkTreePath *copy = gtk_tree_path_copy (path);
1178
1179 /* Delete a copy of the actual path here because the row-deleted
1180 signal may alter the path */
1181 gtk_tree_model_row_deleted (GTK_TREE_MODEL(model)((((GtkTreeModel*) (void *) ((model))))), copy);
1182 gtk_tree_path_free (copy);
1183}
1184
1185static void
1186model_refilter_node (PlumaFileBrowserStore * model,
1187 FileBrowserNode * node,
1188 GtkTreePath ** path)
1189{
1190 gboolean old_visible;
1191 gboolean new_visible;
1192 FileBrowserNodeDir *dir;
1193 GSList *item;
1194 GtkTreeIter iter;
1195 GtkTreePath *tmppath = NULL((void*)0);
1196 gboolean in_tree;
1197
1198 if (node == NULL((void*)0))
1199 return;
1200
1201 old_visible = model_node_visibility (model, node);
1202 model_node_update_visibility (model, node);
1203
1204 in_tree = node_in_tree (model, node);
1205
1206 if (path == NULL((void*)0))
1207 {
1208 if (in_tree)
1209 tmppath = pluma_file_browser_store_get_path_real (model,
1210 node);
1211 else
1212 tmppath = gtk_tree_path_new_first ();
1213
1214 path = &tmppath;
1215 }
1216
1217 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
1218 if (in_tree)
1219 gtk_tree_path_down (*path);
1220
1221 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
1222
1223 for (item = dir->children; item; item = item->next) {
1224 model_refilter_node (model,
1225 (FileBrowserNode *) (item->data),
1226 path);
1227 }
1228
1229 if (in_tree)
1230 gtk_tree_path_up (*path);
1231 }
1232
1233 if (in_tree) {
1234 new_visible = model_node_visibility (model, node);
1235
1236 if (old_visible != new_visible) {
1237 if (old_visible) {
1238 node->inserted = FALSE(0);
1239 row_deleted (model, *path);
1240 } else {
1241 iter.user_data = node;
1242 row_inserted (model, path, &iter);
1243 gtk_tree_path_next (*path);
1244 }
1245 } else if (old_visible) {
1246 gtk_tree_path_next (*path);
1247 }
1248 }
1249
1250 model_check_dummy (model, node);
1251
1252 if (tmppath)
1253 gtk_tree_path_free (tmppath);
1254}
1255
1256static void
1257model_refilter (PlumaFileBrowserStore * model)
1258{
1259 model_refilter_node (model, model->priv->root, NULL((void*)0));
1260}
1261
1262static void
1263file_browser_node_set_name (FileBrowserNode * node)
1264{
1265 g_free (node->name);
1266
1267 if (node->file) {
1268 node->name = pluma_file_browser_utils_file_basename (node->file);
1269 } else {
1270 node->name = NULL((void*)0);
1271 }
1272}
1273
1274static void
1275file_browser_node_init (FileBrowserNode * node, GFile * file,
1276 FileBrowserNode * parent)
1277{
1278 if (file != NULL((void*)0)) {
1279 node->file = g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file));
1280 file_browser_node_set_name (node);
1281 }
1282
1283 node->parent = parent;
1284}
1285
1286static FileBrowserNode *
1287file_browser_node_new (GFile * file, FileBrowserNode * parent)
1288{
1289 FileBrowserNode *node = g_slice_new0 (FileBrowserNode)(FileBrowserNode *) (__extension__ ({ gsize __s = sizeof (FileBrowserNode
); gpointer __p; __p = g_slice_alloc (__s); memset (__p, 0, __s
); __p; }))
;
1290
1291 file_browser_node_init (node, file, parent);
1292 return node;
1293}
1294
1295static FileBrowserNode *
1296file_browser_node_dir_new (PlumaFileBrowserStore * model,
1297 GFile * file, FileBrowserNode * parent)
1298{
1299 FileBrowserNode *node =
1300 (FileBrowserNode *) g_slice_new0 (FileBrowserNodeDir)(FileBrowserNodeDir *) (__extension__ ({ gsize __s = sizeof (
FileBrowserNodeDir); gpointer __p; __p = g_slice_alloc (__s);
memset (__p, 0, __s); __p; }))
;
1301
1302 file_browser_node_init (node, file, parent);
1303
1304 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY;
1305
1306 FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->model = model;
1307
1308 return node;
1309}
1310
1311static void
1312file_browser_node_free_children (PlumaFileBrowserStore * model,
1313 FileBrowserNode * node)
1314{
1315 GSList *item;
1316
1317 if (node == NULL((void*)0))
1318 return;
1319
1320 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
1321 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item;
1322 item = item->next)
1323 file_browser_node_free (model,
1324 (FileBrowserNode *) (item->
1325 data));
1326
1327 g_slist_free (FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children);
1328 FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children = NULL((void*)0);
1329
1330 /* This node is no longer loaded */
1331 node->flags &= ~PLUMA_FILE_BROWSER_STORE_FLAG_LOADED;
1332 }
1333}
1334
1335static void
1336file_browser_node_free (PlumaFileBrowserStore * model,
1337 FileBrowserNode * node)
1338{
1339 gchar *uri;
1340
1341 if (node == NULL((void*)0))
1342 return;
1343
1344 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
1345 {
1346 FileBrowserNodeDir *dir;
1347
1348 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
1349
1350 if (dir->cancellable) {
1351 g_cancellable_cancel (dir->cancellable);
1352 g_object_unref (dir->cancellable);
1353
1354 model_end_loading (model, node);
1355 }
1356
1357 file_browser_node_free_children (model, node);
1358
1359 if (dir->monitor) {
1360 g_file_monitor_cancel (dir->monitor);
1361 g_object_unref (dir->monitor);
1362 }
1363 }
1364
1365 if (node->file)
1366 {
1367 uri = g_file_get_uri (node->file);
1368 g_signal_emit (model, model_signals[UNLOAD], 0, uri);
1369
1370 g_free (uri);
1371 g_object_unref (node->file);
1372 }
1373
1374 if (node->icon)
1375 g_object_unref (node->icon);
1376
1377 if (node->emblem)
1378 g_object_unref (node->emblem);
1379
1380 g_free (node->name);
1381
1382 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
1383 g_slice_free (FileBrowserNodeDir, (FileBrowserNodeDir *)node)do { if (1) g_slice_free1 (sizeof (FileBrowserNodeDir), ((FileBrowserNodeDir
*)node)); else (void) ((FileBrowserNodeDir*) 0 == ((FileBrowserNodeDir
*)node)); } while (0)
;
1384 else
1385 g_slice_free (FileBrowserNode, (FileBrowserNode *)node)do { if (1) g_slice_free1 (sizeof (FileBrowserNode), ((FileBrowserNode
*)node)); else (void) ((FileBrowserNode*) 0 == ((FileBrowserNode
*)node)); } while (0)
;
1386}
1387
1388/**
1389 * model_remove_node_children:
1390 * @model: the #PlumaFileBrowserStore
1391 * @node: the FileBrowserNode to remove
1392 * @path: the path of the node, or NULL to let the path be calculated
1393 * @free_nodes: whether to also remove the nodes from memory
1394 *
1395 * Removes all the children of node from the model. This function is used
1396 * to remove the child nodes from the _model_. Don't use it to just free
1397 * a node.
1398 **/
1399static void
1400model_remove_node_children (PlumaFileBrowserStore * model,
1401 FileBrowserNode * node,
1402 GtkTreePath * path,
1403 gboolean free_nodes)
1404{
1405 FileBrowserNodeDir *dir;
1406 GtkTreePath *path_child;
1407 GSList *list;
1408 GSList *item;
1409
1410 if (node == NULL((void*)0) || !NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
1411 return;
1412
1413 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
1414
1415 if (dir->children == NULL((void*)0))
1416 return;
1417
1418 if (!model_node_visibility (model, node)) {
1419 // Node is invisible and therefore the children can just
1420 // be freed
1421 if (free_nodes)
1422 file_browser_node_free_children (model, node);
1423
1424 return;
1425 }
1426
1427 if (path == NULL((void*)0))
1428 path_child =
1429 pluma_file_browser_store_get_path_real (model, node);
1430 else
1431 path_child = gtk_tree_path_copy (path);
1432
1433 gtk_tree_path_down (path_child);
1434
1435 list = g_slist_copy (dir->children);
1436
1437 for (item = list; item; item = item->next) {
1438 model_remove_node (model, (FileBrowserNode *) (item->data),
1439 path_child, free_nodes);
1440 }
1441
1442 g_slist_free (list);
1443 gtk_tree_path_free (path_child);
1444}
1445
1446/**
1447 * model_remove_node:
1448 * @model: the #PlumaFileBrowserStore
1449 * @node: the FileBrowserNode to remove
1450 * @path: the path to use to remove this node, or NULL to use the path
1451 * calculated from the node itself
1452 * @free_nodes: whether to also remove the nodes from memory
1453 *
1454 * Removes this node and all its children from the model. This function is used
1455 * to remove the node from the _model_. Don't use it to just free
1456 * a node.
1457 **/
1458static void
1459model_remove_node (PlumaFileBrowserStore * model,
1460 FileBrowserNode * node,
1461 GtkTreePath * path,
1462 gboolean free_nodes)
1463{
1464 gboolean free_path = FALSE(0);
1465 FileBrowserNode *parent;
1466
1467 if (path == NULL((void*)0)) {
1468 path =
1469 pluma_file_browser_store_get_path_real (model, node);
1470 free_path = TRUE(!(0));
1471 }
1472
1473 model_remove_node_children (model, node, path, free_nodes);
1474
1475 /* Only delete if the node is visible in the tree (but only when it's
1476 not the virtual root) */
1477 if (model_node_visibility (model, node) && node != model->priv->virtual_root)
1478 {
1479 node->inserted = FALSE(0);
1480 row_deleted (model, path);
1481 }
1482
1483 if (free_path)
1484 gtk_tree_path_free (path);
1485
1486 parent = node->parent;
1487
1488 if (free_nodes) {
1489 /* Remove the node from the parents children list */
1490 if (parent)
1491 FILE_BROWSER_NODE_DIR (node->parent)((FileBrowserNodeDir *)(node->parent))->children =
1492 g_slist_remove (FILE_BROWSER_NODE_DIR((FileBrowserNodeDir *)(node->parent))
1493 (node->parent)((FileBrowserNodeDir *)(node->parent))->children,
1494 node);
1495 }
1496
1497 /* If this is the virtual root, than set the parent as the virtual root */
1498 if (node == model->priv->virtual_root)
1499 set_virtual_root_from_node (model, parent);
1500 else if (parent && model_node_visibility (model, parent) && !(free_nodes && NODE_IS_DUMMY(node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
))
1501 model_check_dummy (model, parent);
1502
1503 /* Now free the node if necessary */
1504 if (free_nodes)
1505 file_browser_node_free (model, node);
1506}
1507
1508/**
1509 * model_clear:
1510 * @model: the #PlumaFileBrowserStore
1511 * @free_nodes: whether to also remove the nodes from memory
1512 *
1513 * Removes all nodes from the model. This function is used
1514 * to remove all the nodes from the _model_. Don't use it to just free the
1515 * nodes in the model.
1516 **/
1517static void
1518model_clear (PlumaFileBrowserStore * model, gboolean free_nodes)
1519{
1520 GtkTreePath *path;
1521 FileBrowserNodeDir *dir;
1522 FileBrowserNode *dummy;
1523
1524 path = gtk_tree_path_new ();
1525 model_remove_node_children (model, model->priv->virtual_root, path,
1526 free_nodes);
1527 gtk_tree_path_free (path);
1528
1529 /* Remove the dummy if there is one */
1530 if (model->priv->virtual_root) {
1531 dir = FILE_BROWSER_NODE_DIR (model->priv->virtual_root)((FileBrowserNodeDir *)(model->priv->virtual_root));
1532
1533 if (dir->children != NULL((void*)0)) {
1534 dummy = (FileBrowserNode *) (dir->children->data);
1535
1536 if (NODE_IS_DUMMY (dummy)(((dummy)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
1537 && model_node_visibility (model, dummy)) {
1538 path = gtk_tree_path_new_first ();
1539
1540 dummy->inserted = FALSE(0);
1541 row_deleted (model, path);
1542 gtk_tree_path_free (path);
1543 }
1544 }
1545 }
1546}
1547
1548static void
1549file_browser_node_unload (PlumaFileBrowserStore * model,
1550 FileBrowserNode * node, gboolean remove_children)
1551{
1552 FileBrowserNodeDir *dir;
1553
1554 if (node == NULL((void*)0))
1555 return;
1556
1557 if (!NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
|| !NODE_LOADED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
)
1558 return;
1559
1560 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
1561
1562 if (remove_children)
1563 model_remove_node_children (model, node, NULL((void*)0), TRUE(!(0)));
1564
1565 if (dir->cancellable) {
1566 g_cancellable_cancel (dir->cancellable);
1567 g_object_unref (dir->cancellable);
1568
1569 model_end_loading (model, node);
1570 dir->cancellable = NULL((void*)0);
1571 }
1572
1573 if (dir->monitor) {
1574 g_file_monitor_cancel (dir->monitor);
1575 g_object_unref (dir->monitor);
1576
1577 dir->monitor = NULL((void*)0);
1578 }
1579
1580 node->flags &= ~PLUMA_FILE_BROWSER_STORE_FLAG_LOADED;
1581}
1582
1583static void
1584model_recomposite_icon_real (PlumaFileBrowserStore * tree_model,
1585 FileBrowserNode * node,
1586 GFileInfo * info)
1587{
1588 GdkPixbuf *icon;
1589
1590 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_301
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_301 = 1; else _g_boolean_var_301 =
0; _g_boolean_var_301; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return; } } while (0)
;
1591 g_return_if_fail (node != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_302
; if (node != ((void*)0)) _g_boolean_var_302 = 1; else _g_boolean_var_302
= 0; _g_boolean_var_302; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "node != NULL"); return
; } } while (0)
;
1592
1593 if (node->file == NULL((void*)0))
1594 return;
1595
1596 if (info) {
1597 GIcon *gicon = g_file_info_get_icon (info);
1598 if (gicon != NULL((void*)0))
1599 icon = pluma_file_browser_utils_pixbuf_from_icon (gicon, GTK_ICON_SIZE_MENU);
1600 else
1601 icon = NULL((void*)0);
1602 } else {
1603 icon = pluma_file_browser_utils_pixbuf_from_file (node->file, GTK_ICON_SIZE_MENU);
1604 }
1605
1606 if (node->icon)
1607 g_object_unref (node->icon);
1608
1609 if (node->emblem) {
1610 gint icon_size;
1611
1612 gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL((void*)0), &icon_size);
1613
1614 if (icon == NULL((void*)0)) {
1615 node->icon =
1616 gdk_pixbuf_new (gdk_pixbuf_get_colorspace (node->emblem),
1617 gdk_pixbuf_get_has_alpha (node->emblem),
1618 gdk_pixbuf_get_bits_per_sample (node->emblem),
1619 icon_size,
1620 icon_size);
1621 } else {
1622 node->icon = gdk_pixbuf_copy (icon);
1623 g_object_unref (icon);
1624 }
1625
1626 gdk_pixbuf_composite (node->emblem, node->icon,
1627 icon_size - 10, icon_size - 10, 10,
1628 10, icon_size - 10, icon_size - 10,
1629 1, 1, GDK_INTERP_NEAREST, 255);
1630 } else {
1631 node->icon = icon;
1632 }
1633}
1634
1635static void
1636model_recomposite_icon (PlumaFileBrowserStore * tree_model,
1637 GtkTreeIter * iter)
1638{
1639 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_303
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_303 = 1; else _g_boolean_var_303 =
0; _g_boolean_var_303; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return; } } while (0)
;
1640 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_304
; if (iter != ((void*)0)) _g_boolean_var_304 = 1; else _g_boolean_var_304
= 0; _g_boolean_var_304; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
1641 g_return_if_fail (iter->user_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_305
; if (iter->user_data != ((void*)0)) _g_boolean_var_305 = 1
; else _g_boolean_var_305 = 0; _g_boolean_var_305; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return; } } while
(0)
;
1642
1643 model_recomposite_icon_real (tree_model,
1644 (FileBrowserNode *) (iter->user_data),
1645 NULL((void*)0));
1646}
1647
1648static FileBrowserNode *
1649model_create_dummy_node (PlumaFileBrowserStore * model,
1650 FileBrowserNode * parent)
1651{
1652 FileBrowserNode *dummy;
1653
1654 dummy = file_browser_node_new (NULL((void*)0), parent);
1655 dummy->name = g_strdup (_("(Empty)"))g_strdup_inline (((char *) g_dgettext ("pluma", "(Empty)")));
1656
1657 dummy->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY;
1658 dummy->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1659
1660 return dummy;
1661}
1662
1663static FileBrowserNode *
1664model_add_dummy_node (PlumaFileBrowserStore * model,
1665 FileBrowserNode * parent)
1666{
1667 FileBrowserNode *dummy;
1668
1669 dummy = model_create_dummy_node (model, parent);
1670
1671 if (model_node_visibility (model, parent))
1672 dummy->flags &= ~PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1673
1674 model_add_node (model, dummy, parent);
1675
1676 return dummy;
1677}
1678
1679static void
1680model_check_dummy (PlumaFileBrowserStore * model, FileBrowserNode * node)
1681{
1682 // Hide the dummy child if needed
1683 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
1684 FileBrowserNode *dummy;
1685 GtkTreeIter iter;
1686 GtkTreePath *path;
1687 guint flags;
1688 FileBrowserNodeDir *dir;
1689
1690 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
1691
1692 if (dir->children == NULL((void*)0)) {
1693 model_add_dummy_node (model, node);
1694 return;
1695 }
1696
1697 dummy = (FileBrowserNode *) (dir->children->data);
1698
1699 if (!NODE_IS_DUMMY (dummy)(((dummy)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
) {
1700 dummy = model_create_dummy_node (model, node);
1701 dir->children = g_slist_prepend (dir->children, dummy);
1702 }
1703
1704 if (!model_node_visibility (model, node)) {
1705 dummy->flags |=
1706 PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1707 return;
1708 }
1709
1710 /* Temporarily set the node to invisible to check
1711 * for real children */
1712 flags = dummy->flags;
1713 dummy->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1714
1715 if (!filter_tree_model_iter_has_child_real (model, node)) {
1716 dummy->flags &=
1717 ~PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1718
1719 if (FILE_IS_HIDDEN (flags)(flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN)) {
1720 // Was hidden, needs to be inserted
1721 iter.user_data = dummy;
1722 path =
1723 pluma_file_browser_store_get_path_real
1724 (model, dummy);
1725
1726 row_inserted (model, &path, &iter);
1727 gtk_tree_path_free (path);
1728 }
1729 } else {
1730 if (!FILE_IS_HIDDEN (flags)(flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN)) {
1731 // Was shown, needs to be removed
1732
1733 // To get the path we need to set it to visible temporarily
1734 dummy->flags &=
1735 ~PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1736 path =
1737 pluma_file_browser_store_get_path_real
1738 (model, dummy);
1739 dummy->flags |=
1740 PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1741
1742 dummy->inserted = FALSE(0);
1743 row_deleted (model, path);
1744 gtk_tree_path_free (path);
1745 }
1746 }
1747 }
1748}
1749
1750static void
1751insert_node_sorted (PlumaFileBrowserStore * model,
1752 FileBrowserNode * child,
1753 FileBrowserNode * parent)
1754{
1755 FileBrowserNodeDir *dir;
1756
1757 dir = FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent));
1758
1759 if (model->priv->sort_func == NULL((void*)0)) {
1760 dir->children = g_slist_append (dir->children, child);
1761 } else {
1762 dir->children =
1763 g_slist_insert_sorted (dir->children, child,
1764 (GCompareFunc) (model->priv->
1765 sort_func));
1766 }
1767}
1768
1769static void
1770model_add_node (PlumaFileBrowserStore * model, FileBrowserNode * child,
1771 FileBrowserNode * parent)
1772{
1773 /* Add child to parents children */
1774 insert_node_sorted (model, child, parent);
1775
1776 if (model_node_visibility (model, parent) &&
1777 model_node_visibility (model, child)) {
1778 GtkTreeIter iter;
1779 GtkTreePath *path;
1780
1781 iter.user_data = child;
1782 path = pluma_file_browser_store_get_path_real (model, child);
1783
1784 /* Emit row inserted */
1785 row_inserted (model, &path, &iter);
1786 gtk_tree_path_free (path);
1787 }
1788
1789 model_check_dummy (model, parent);
1790 model_check_dummy (model, child);
1791}
1792
1793static void
1794model_add_nodes_batch (PlumaFileBrowserStore * model,
1795 GSList * children,
1796 FileBrowserNode * parent)
1797{
1798 GSList *sorted_children;
1799 GSList *child;
1800 GSList *prev;
1801 GSList *l;
1802 FileBrowserNodeDir *dir;
1803
1804 dir = FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent));
1805
1806 sorted_children = g_slist_sort (children, (GCompareFunc) model->priv->sort_func);
1807
1808 child = sorted_children;
1809 l = dir->children;
1810 prev = NULL((void*)0);
1811
1812 model_check_dummy (model, parent);
1813
1814 while (child) {
1815 FileBrowserNode *node = child->data;
1816 GtkTreeIter iter;
1817 GtkTreePath *path;
1818
1819 /* reached the end of the first list, just append the second */
1820 if (l == NULL((void*)0)) {
1821
1822 dir->children = g_slist_concat (dir->children, child);
1823
1824 for (l = child; l; l = l->next) {
1825 if (model_node_visibility (model, parent) &&
1826 model_node_visibility (model, l->data)) {
1827 iter.user_data = l->data;
1828 path = pluma_file_browser_store_get_path_real (model, l->data);
1829
1830 // Emit row inserted
1831 row_inserted (model, &path, &iter);
1832 gtk_tree_path_free (path);
1833 }
1834
1835 model_check_dummy (model, l->data);
1836 }
1837
1838 break;
1839 }
1840
1841 if (model->priv->sort_func (l->data, node) > 0) {
1842 GSList *next_child;
1843
1844 if (prev == NULL((void*)0)) {
1845 /* prepend to the list */
1846 dir->children = g_slist_prepend (dir->children, child);
1847 } else {
1848 prev->next = child;
1849 }
1850
1851 next_child = child->next;
1852 prev = child;
1853 child->next = l;
1854 child = next_child;
1855
1856 if (model_node_visibility (model, parent) &&
1857 model_node_visibility (model, node)) {
1858 iter.user_data = node;
1859 path = pluma_file_browser_store_get_path_real (model, node);
1860
1861 // Emit row inserted
1862 row_inserted (model, &path, &iter);
1863 gtk_tree_path_free (path);
1864 }
1865
1866 model_check_dummy (model, node);
1867
1868 /* try again at the same l position with the
1869 * next child */
1870 } else {
1871
1872 /* Move to the next item in the list */
1873 prev = l;
1874 l = l->next;
1875 }
1876 }
1877}
1878
1879static gchar const *
1880backup_content_type (GFileInfo * info)
1881{
1882 gchar const * content;
1883
1884 if (!g_file_info_get_is_backup (info))
1885 return NULL((void*)0);
1886
1887 content = g_file_info_get_content_type (info);
1888
1889 if (!content || g_content_type_equals (content, "application/x-trash"))
1890 return "text/plain";
1891
1892 return content;
1893}
1894
1895static void
1896file_browser_node_set_from_info (PlumaFileBrowserStore * model,
1897 FileBrowserNode * node,
1898 GFileInfo * info,
1899 gboolean isadded)
1900{
1901 gchar const * content;
1902 gboolean free_info = FALSE(0);
1903 GtkTreePath * path;
1904 gchar * uri;
1905 GError * error = NULL((void*)0);
1906
1907 if (info == NULL((void*)0)) {
1908 info = g_file_query_info (node->file,
1909 STANDARD_ATTRIBUTE_TYPES"standard::type" "," "standard::is-hidden" "," "standard::is-backup"
"," "standard::name" "," "standard::content-type" "," "standard::icon"
,
1910 G_FILE_QUERY_INFO_NONE,
1911 NULL((void*)0),
1912 &error);
1913
1914 if (!info) {
1915 if (!(error->domain == G_IO_ERRORg_io_error_quark() && error->code == G_IO_ERROR_NOT_FOUND)) {
1916 uri = g_file_get_uri (node->file);
1917 g_warning ("Could not get info for %s: %s", uri, error->message);
1918 g_free (uri);
1919 }
1920 g_error_free (error);
1921
1922 return;
1923 }
1924
1925 free_info = TRUE(!(0));
1926 }
1927
1928 if (g_file_info_get_is_hidden (info) || g_file_info_get_is_backup (info))
1929 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
1930
1931 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
1932 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY;
1933 else {
1934 if (!(content = backup_content_type (info)))
1935 content = g_file_info_get_content_type (info);
1936
1937 if (!content ||
1938 g_content_type_is_unknown (content) ||
1939 g_content_type_is_a (content, "text/plain"))
1940 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_IS_TEXT;
1941 }
1942
1943 model_recomposite_icon_real (model, node, info);
1944
1945 if (free_info)
1946 g_object_unref (info);
1947
1948 if (isadded) {
1949 path = pluma_file_browser_store_get_path_real (model, node);
1950 model_refilter_node (model, node, &path);
1951 gtk_tree_path_free (path);
1952
1953 model_check_dummy (model, node->parent);
1954 } else {
1955 model_node_update_visibility (model, node);
1956 }
1957}
1958
1959static FileBrowserNode *
1960node_list_contains_file (GSList *children, GFile * file)
1961{
1962 GSList *item;
1963
1964 for (item = children; item; item = item->next) {
1965 FileBrowserNode *node;
1966
1967 node = (FileBrowserNode *) (item->data);
1968
1969 if (node->file != NULL((void*)0)
1970 && g_file_equal (node->file, file))
1971 return node;
1972 }
1973
1974 return NULL((void*)0);
1975}
1976
1977static FileBrowserNode *
1978model_add_node_from_file (PlumaFileBrowserStore * model,
1979 FileBrowserNode * parent,
1980 GFile * file,
1981 GFileInfo * info)
1982{
1983 FileBrowserNode *node;
1984 gboolean free_info = FALSE(0);
1985 GError * error = NULL((void*)0);
1986
1987 if ((node = node_list_contains_file (FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent))->children, file)) == NULL((void*)0)) {
1988 if (info == NULL((void*)0)) {
1989 info = g_file_query_info (file,
1990 STANDARD_ATTRIBUTE_TYPES"standard::type" "," "standard::is-hidden" "," "standard::is-backup"
"," "standard::name" "," "standard::content-type" "," "standard::icon"
,
1991 G_FILE_QUERY_INFO_NONE,
1992 NULL((void*)0),
1993 &error);
1994 free_info = TRUE(!(0));
1995 }
1996
1997 if (!info) {
1998 g_warning ("Error querying file info: %s", error->message);
1999 g_error_free (error);
2000
2001 /* FIXME: What to do now then... */
2002 node = file_browser_node_new (file, parent);
2003 } else if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
2004 node = file_browser_node_dir_new (model, file, parent);
2005 } else {
2006 node = file_browser_node_new (file, parent);
2007 }
2008
2009 file_browser_node_set_from_info (model, node, info, FALSE(0));
2010 model_add_node (model, node, parent);
2011
2012 if (info && free_info)
2013 g_object_unref (info);
2014 }
2015
2016 return node;
2017}
2018
2019/* We pass in a copy of the list of parent->children so that we do
2020 * not have to check if a file already exists among the ones we just
2021 * added */
2022static void
2023model_add_nodes_from_files (PlumaFileBrowserStore * model,
2024 FileBrowserNode * parent,
2025 GSList * original_children,
2026 GList * files)
2027{
2028 GList *item;
2029 GSList *nodes = NULL((void*)0);
2030
2031 for (item = files; item; item = item->next) {
2032 GFileInfo *info = G_FILE_INFO (item->data)((((GFileInfo*) (void *) ((item->data)))));
2033 GFileType type;
2034 gchar const * name;
2035 GFile * file;
2036 FileBrowserNode *node;
2037
2038 type = g_file_info_get_file_type (info);
2039
2040 /* Skip all non regular, non directory files */
2041 if (type != G_FILE_TYPE_REGULAR &&
2042 type != G_FILE_TYPE_DIRECTORY &&
2043 type != G_FILE_TYPE_SYMBOLIC_LINK) {
2044 g_object_unref (info);
2045 continue;
2046 }
2047
2048 name = g_file_info_get_name (info);
2049
2050 /* Skip '.' and '..' directories */
2051 if (type == G_FILE_TYPE_DIRECTORY &&
2052 (strcmp (name, ".") == 0 ||
2053 strcmp (name, "..") == 0)) {
2054 continue;
2055 }
2056
2057 file = g_file_get_child (parent->file, name);
2058
2059 if ((node = node_list_contains_file (original_children, file)) == NULL((void*)0)) {
Although the value stored to 'node' is used in the enclosing expression, the value is never actually read from 'node'
2060
2061 if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
2062 node = file_browser_node_dir_new (model, file, parent);
2063 } else {
2064 node = file_browser_node_new (file, parent);
2065 }
2066
2067 file_browser_node_set_from_info (model, node, info, FALSE(0));
2068
2069 nodes = g_slist_prepend (nodes, node);
2070 }
2071
2072 g_object_unref (file);
2073 g_object_unref (info);
2074 }
2075
2076 if (nodes)
2077 model_add_nodes_batch (model, nodes, parent);
2078}
2079
2080static FileBrowserNode *
2081model_add_node_from_dir (PlumaFileBrowserStore * model,
2082 FileBrowserNode * parent,
2083 GFile * file)
2084{
2085 FileBrowserNode *node;
2086
2087 /* Check if it already exists */
2088 if ((node = node_list_contains_file (FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent))->children, file)) == NULL((void*)0)) {
2089 node = file_browser_node_dir_new (model, file, parent);
2090 file_browser_node_set_from_info (model, node, NULL((void*)0), FALSE(0));
2091
2092 if (node->name == NULL((void*)0)) {
2093 file_browser_node_set_name (node);
2094 }
2095
2096 if (node->icon == NULL((void*)0)) {
2097 node->icon = pluma_file_browser_utils_pixbuf_from_theme ("folder", GTK_ICON_SIZE_MENU);
2098 }
2099
2100 model_add_node (model, node, parent);
2101 }
2102
2103 return node;
2104}
2105
2106static void
2107on_directory_monitor_event (GFileMonitor * monitor,
2108 GFile * file,
2109 GFile * other_file,
2110 GFileMonitorEvent event_type,
2111 FileBrowserNode * parent)
2112{
2113 FileBrowserNode *node;
2114 FileBrowserNodeDir *dir = FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent));
2115
2116 switch (event_type) {
2117 case G_FILE_MONITOR_EVENT_DELETED:
2118 node = node_list_contains_file (dir->children, file);
2119
2120 if (node != NULL((void*)0)) {
2121 model_remove_node (dir->model, node, NULL((void*)0), TRUE(!(0)));
2122 }
2123 break;
2124 case G_FILE_MONITOR_EVENT_CREATED:
2125 if (g_file_query_exists (file, NULL((void*)0))) {
2126 model_add_node_from_file (dir->model, parent, file, NULL((void*)0));
2127 }
2128
2129 break;
2130 default:
2131 break;
2132 }
2133}
2134
2135static void
2136async_node_free (AsyncNode *async)
2137{
2138 g_object_unref (async->cancellable);
2139 g_slist_free (async->original_children);
2140 g_free (async);
2141}
2142
2143static void
2144model_iterate_next_files_cb (GFileEnumerator * enumerator,
2145 GAsyncResult * result,
2146 AsyncNode * async)
2147{
2148 GList * files;
2149 GError * error = NULL((void*)0);
2150 FileBrowserNodeDir * dir = async->dir;
2151 FileBrowserNode * parent = (FileBrowserNode *)dir;
2152
2153 files = g_file_enumerator_next_files_finish (enumerator, result, &error);
2154
2155 if (files == NULL((void*)0)) {
2156 g_file_enumerator_close (enumerator, NULL((void*)0), NULL((void*)0));
2157 async_node_free (async);
2158
2159 if (!error)
2160 {
2161 /* We're done loading */
2162 g_object_unref (dir->cancellable);
2163 dir->cancellable = NULL((void*)0);
2164
2165/*
2166 * FIXME: This is temporarly, it is a bug in gio:
2167 * http://bugzilla.gnome.org/show_bug.cgi?id=565924
2168 */
2169 if (g_file_is_native (parent->file) && dir->monitor == NULL((void*)0)) {
2170 dir->monitor = g_file_monitor_directory (parent->file,
2171 G_FILE_MONITOR_NONE,
2172 NULL((void*)0),
2173 NULL((void*)0));
2174 if (dir->monitor != NULL((void*)0))
2175 {
2176 g_signal_connect (dir->monitor,g_signal_connect_data ((dir->monitor), ("changed"), (((GCallback
) (on_directory_monitor_event))), (parent), ((void*)0), (GConnectFlags
) 0)
2177 "changed",g_signal_connect_data ((dir->monitor), ("changed"), (((GCallback
) (on_directory_monitor_event))), (parent), ((void*)0), (GConnectFlags
) 0)
2178 G_CALLBACK (on_directory_monitor_event),g_signal_connect_data ((dir->monitor), ("changed"), (((GCallback
) (on_directory_monitor_event))), (parent), ((void*)0), (GConnectFlags
) 0)
2179 parent)g_signal_connect_data ((dir->monitor), ("changed"), (((GCallback
) (on_directory_monitor_event))), (parent), ((void*)0), (GConnectFlags
) 0)
;
2180 }
2181 }
2182
2183 model_check_dummy (dir->model, parent);
2184 model_end_loading (dir->model, parent);
2185 } else {
2186 /* Simply return if we were cancelled */
2187 if (error->domain == G_IO_ERRORg_io_error_quark() && error->code == G_IO_ERROR_CANCELLED)
2188 return;
2189
2190 /* Otherwise handle the error appropriately */
2191 g_signal_emit (dir->model,
2192 model_signals[ERROR],
2193 0,
2194 PLUMA_FILE_BROWSER_ERROR_LOAD_DIRECTORY,
2195 error->message);
2196
2197 file_browser_node_unload (dir->model, (FileBrowserNode *)parent, TRUE(!(0)));
2198 g_error_free (error);
2199 }
2200 } else if (g_cancellable_is_cancelled (async->cancellable)) {
2201 /* Check cancel state manually */
2202 g_file_enumerator_close (enumerator, NULL((void*)0), NULL((void*)0));
2203 async_node_free (async);
2204 } else {
2205 model_add_nodes_from_files (dir->model, parent, async->original_children, files);
2206
2207 g_list_free (files);
2208 next_files_async (enumerator, async);
2209 }
2210}
2211
2212static void
2213next_files_async (GFileEnumerator * enumerator,
2214 AsyncNode * async)
2215{
2216 g_file_enumerator_next_files_async (enumerator,
2217 DIRECTORY_LOAD_ITEMS_PER_CALLBACK100,
2218 G_PRIORITY_DEFAULT0,
2219 async->cancellable,
2220 (GAsyncReadyCallback)model_iterate_next_files_cb,
2221 async);
2222}
2223
2224static void
2225model_iterate_children_cb (GFile * file,
2226 GAsyncResult * result,
2227 AsyncNode * async)
2228{
2229 GError * error = NULL((void*)0);
2230 GFileEnumerator * enumerator;
2231
2232 if (g_cancellable_is_cancelled (async->cancellable))
2233 {
2234 async_node_free (async);
2235 return;
2236 }
2237
2238 enumerator = g_file_enumerate_children_finish (file, result, &error);
2239
2240 if (enumerator == NULL((void*)0)) {
2241 /* Simply return if we were cancelled or if the dir is not there */
2242 FileBrowserNodeDir *dir = async->dir;
2243
2244 /* Otherwise handle the error appropriately */
2245 g_signal_emit (dir->model,
2246 model_signals[ERROR],
2247 0,
2248 PLUMA_FILE_BROWSER_ERROR_LOAD_DIRECTORY,
2249 error->message);
2250
2251 file_browser_node_unload (dir->model, (FileBrowserNode *)dir, TRUE(!(0)));
2252 g_error_free (error);
2253 async_node_free (async);
2254 } else {
2255 next_files_async (enumerator, async);
2256 }
2257}
2258
2259static void
2260model_load_directory (PlumaFileBrowserStore * model,
2261 FileBrowserNode * node)
2262{
2263 FileBrowserNodeDir *dir;
2264 AsyncNode *async;
2265
2266 g_return_if_fail (NODE_IS_DIR (node))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_306
; if ((((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))) _g_boolean_var_306 = 1; else _g_boolean_var_306 = 0; _g_boolean_var_306
; }), 1))) { } else { g_return_if_fail_warning (((gchar*) 0),
((const char*) (__func__)), "NODE_IS_DIR (node)"); return; }
} while (0)
;
2267
2268 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
2269
2270 /* Cancel a previous load */
2271 if (dir->cancellable != NULL((void*)0)) {
2272 file_browser_node_unload (dir->model, node, TRUE(!(0)));
2273 }
2274
2275 node->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_LOADED;
2276 model_begin_loading (model, node);
2277
2278 dir->cancellable = g_cancellable_new ();
2279
2280 async = g_new (AsyncNode, 1)(AsyncNode *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (AsyncNode); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
2281 async->dir = dir;
2282 async->cancellable = g_object_ref (dir->cancellable)((__typeof__ (dir->cancellable)) (g_object_ref) (dir->cancellable
))
;
2283 async->original_children = g_slist_copy (dir->children);
2284
2285 /* Start loading async */
2286 g_file_enumerate_children_async (node->file,
2287 STANDARD_ATTRIBUTE_TYPES"standard::type" "," "standard::is-hidden" "," "standard::is-backup"
"," "standard::name" "," "standard::content-type" "," "standard::icon"
,
2288 G_FILE_QUERY_INFO_NONE,
2289 G_PRIORITY_DEFAULT0,
2290 async->cancellable,
2291 (GAsyncReadyCallback)model_iterate_children_cb,
2292 async);
2293}
2294
2295static GList *
2296get_parent_files (PlumaFileBrowserStore * model, GFile * file)
2297{
2298 GList * result = NULL((void*)0);
2299
2300 result = g_list_prepend (result, g_object_ref (file)((__typeof__ (file)) (g_object_ref) (file)));
2301
2302 while ((file = g_file_get_parent (file))) {
2303 if (g_file_equal (file, model->priv->root->file)) {
2304 g_object_unref (file);
2305 break;
2306 }
2307
2308 result = g_list_prepend (result, file);
2309 }
2310
2311 return result;
2312}
2313
2314static void
2315model_fill (PlumaFileBrowserStore * model, FileBrowserNode * node,
2316 GtkTreePath ** path)
2317{
2318 gboolean free_path = FALSE(0);
2319 GtkTreeIter iter = {0,};
2320 GSList *item;
2321 FileBrowserNode *child;
2322
2323 if (node == NULL((void*)0)) {
2324 node = model->priv->virtual_root;
2325 *path = gtk_tree_path_new ();
2326 free_path = TRUE(!(0));
2327 }
2328
2329 if (*path == NULL((void*)0)) {
2330 *path =
2331 pluma_file_browser_store_get_path_real (model, node);
2332 free_path = TRUE(!(0));
2333 }
2334
2335 if (!model_node_visibility (model, node)) {
2336 if (free_path)
2337 gtk_tree_path_free (*path);
2338
2339 return;
2340 }
2341
2342 if (node != model->priv->virtual_root) {
2343 /* Insert node */
2344 iter.user_data = node;
2345
2346 row_inserted(model, path, &iter);
2347 }
2348
2349 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
2350 /* Go to the first child */
2351 gtk_tree_path_down (*path);
2352
2353 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item;
2354 item = item->next) {
2355 child = (FileBrowserNode *) (item->data);
2356
2357 if (model_node_visibility (model, child)) {
2358 model_fill (model, child, path);
2359
2360 /* Increase path for next child */
2361 gtk_tree_path_next (*path);
2362 }
2363 }
2364
2365 /* Move back up to node path */
2366 gtk_tree_path_up (*path);
2367 }
2368
2369 model_check_dummy (model, node);
2370
2371 if (free_path)
2372 gtk_tree_path_free (*path);
2373}
2374
2375static void
2376set_virtual_root_from_node (PlumaFileBrowserStore * model,
2377 FileBrowserNode * node)
2378{
2379 FileBrowserNode *next;
2380 FileBrowserNode *prev;
2381 FileBrowserNode *check;
2382 FileBrowserNodeDir *dir;
2383 GSList *item;
2384 GSList *copy;
2385 GtkTreePath *empty = NULL((void*)0);
2386
2387 g_assert (node != NULL)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_307
; if (node != ((void*)0)) _g_boolean_var_307 = 1; else _g_boolean_var_307
= 0; _g_boolean_var_307; }), 1)) ; else g_assertion_message_expr
(((gchar*) 0), "pluma-file-browser-store.c", 2387, ((const char
*) (__func__)), "node != NULL"); } while (0)
;
2388
2389 prev = node;
2390 next = prev->parent;
2391
2392 /* Free all the nodes below that we don't need in cache */
2393 while (prev != model->priv->root) {
2394 dir = FILE_BROWSER_NODE_DIR (next)((FileBrowserNodeDir *)(next));
2395 copy = g_slist_copy (dir->children);
2396
2397 for (item = copy; item; item = item->next) {
2398 check = (FileBrowserNode *) (item->data);
2399
2400 if (prev == node) {
2401 /* Only free the children, keeping this depth in cache */
2402 if (check != node) {
2403 file_browser_node_free_children
2404 (model, check);
2405 file_browser_node_unload (model,
2406 check,
2407 FALSE(0));
2408 }
2409 } else if (check != prev) {
2410 /* Only free when the node is not in the chain */
2411 dir->children =
2412 g_slist_remove (dir->children, check);
2413 file_browser_node_free (model, check);
2414 }
2415 }
2416
2417 if (prev != node)
2418 file_browser_node_unload (model, next, FALSE(0));
2419
2420 g_slist_free (copy);
2421 prev = next;
2422 next = prev->parent;
2423 }
2424
2425 /* Free all the nodes up that we don't need in cache */
2426 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item;
2427 item = item->next) {
2428 check = (FileBrowserNode *) (item->data);
2429
2430 if (NODE_IS_DIR (check)(((check)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
2431 for (copy =
2432 FILE_BROWSER_NODE_DIR (check)((FileBrowserNodeDir *)(check))->children; copy;
2433 copy = copy->next) {
2434 file_browser_node_free_children (model,
2435 (FileBrowserNode
2436 *)
2437 (copy->
2438 data));
2439 file_browser_node_unload (model,
2440 (FileBrowserNode
2441 *) (copy->data),
2442 FALSE(0));
2443 }
2444 } else if (NODE_IS_DUMMY (check)(((check)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
) {
2445 check->flags |=
2446 PLUMA_FILE_BROWSER_STORE_FLAG_IS_HIDDEN;
2447 }
2448 }
2449
2450 /* Now finally, set the virtual root, and load it up! */
2451 model->priv->virtual_root = node;
2452
2453 /* Notify that the virtual-root has changed before loading up new nodes so that the
2454 "root_changed" signal can be emitted before any "inserted" signals */
2455 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "virtual-root");
2456
2457 model_fill (model, NULL((void*)0), &empty);
2458
2459 if (!NODE_LOADED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
)
2460 model_load_directory (model, node);
2461}
2462
2463static void
2464set_virtual_root_from_file (PlumaFileBrowserStore * model,
2465 GFile * file)
2466{
2467 GList * files;
2468 GList * item;
2469 FileBrowserNode * parent;
2470 GFile * check;
2471
2472 /* Always clear the model before altering the nodes */
2473 model_clear (model, FALSE(0));
2474
2475 /* Create the node path, get all the uri's */
2476 files = get_parent_files (model, file);
2477 parent = model->priv->root;
2478
2479 for (item = files; item; item = item->next) {
2480 check = G_FILE (item->data)((((GFile*) (void *) ((item->data)))));
2481
2482 parent = model_add_node_from_dir (model, parent, check);
2483 g_object_unref (check);
2484 }
2485
2486 g_list_free (files);
2487 set_virtual_root_from_node (model, parent);
2488}
2489
2490static FileBrowserNode *
2491model_find_node_children (PlumaFileBrowserStore * model,
2492 FileBrowserNode * parent,
2493 GFile * file)
2494{
2495 FileBrowserNodeDir *dir;
2496 FileBrowserNode *child;
2497 FileBrowserNode *result;
2498 GSList *children;
2499
2500 if (!NODE_IS_DIR (parent)(((parent)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
)
2501 return NULL((void*)0);
2502
2503 dir = FILE_BROWSER_NODE_DIR (parent)((FileBrowserNodeDir *)(parent));
2504
2505 for (children = dir->children; children; children = children->next) {
2506 child = (FileBrowserNode *)(children->data);
2507
2508 result = model_find_node (model, child, file);
2509
2510 if (result)
2511 return result;
2512 }
2513
2514 return NULL((void*)0);
2515}
2516
2517static FileBrowserNode *
2518model_find_node (PlumaFileBrowserStore * model,
2519 FileBrowserNode * node,
2520 GFile * file)
2521{
2522 if (node == NULL((void*)0))
2523 node = model->priv->root;
2524
2525 if (node->file && g_file_equal (node->file, file))
2526 return node;
2527
2528 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
&& g_file_has_prefix (file, node->file))
2529 return model_find_node_children (model, node, file);
2530
2531 return NULL((void*)0);
2532}
2533
2534static GQuark
2535pluma_file_browser_store_error_quark (void)
2536{
2537 static GQuark quark = 0;
2538
2539 if (G_UNLIKELY (quark == 0)(__builtin_expect (__extension__ ({ int _g_boolean_var_308; if
(quark == 0) _g_boolean_var_308 = 1; else _g_boolean_var_308
= 0; _g_boolean_var_308; }), 0))
) {
2540 quark = g_quark_from_string ("pluma_file_browser_store_error");
2541 }
2542
2543 return quark;
2544}
2545
2546static GFile *
2547unique_new_name (GFile * directory, gchar const * name)
2548{
2549 GFile * newuri = NULL((void*)0);
2550 guint num = 0;
2551 gchar * newname;
2552
2553 while (newuri == NULL((void*)0) || g_file_query_exists (newuri, NULL((void*)0))) {
2554 if (newuri != NULL((void*)0))
2555 g_object_unref (newuri);
2556
2557 if (num == 0)
2558 newname = g_strdup (name)g_strdup_inline (name);
2559 else
2560 newname = g_strdup_printf ("%s(%d)", name, num);
2561
2562 newuri = g_file_get_child (directory, newname);
2563 g_free (newname);
2564
2565 ++num;
2566 }
2567
2568 return newuri;
2569}
2570
2571static PlumaFileBrowserStoreResult
2572model_root_mounted (PlumaFileBrowserStore * model, gchar const * virtual_root)
2573{
2574 model_check_dummy (model, model->priv->root);
2575 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "root");
2576
2577 if (virtual_root != NULL((void*)0))
2578 return
2579 pluma_file_browser_store_set_virtual_root_from_string
2580 (model, virtual_root);
2581 else
2582 set_virtual_root_from_node (model,
2583 model->priv->root);
2584
2585 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2586}
2587
2588static void
2589handle_root_error (PlumaFileBrowserStore * model, GError *error)
2590{
2591 FileBrowserNode * root;
2592
2593 g_signal_emit (model,
2594 model_signals[ERROR],
2595 0,
2596 PLUMA_FILE_BROWSER_ERROR_SET_ROOT,
2597 error->message);
2598
2599 /* Set the virtual root to the root */
2600 root = model->priv->root;
2601 model->priv->virtual_root = root;
2602
2603 /* Set the root to be loaded */
2604 root->flags |= PLUMA_FILE_BROWSER_STORE_FLAG_LOADED;
2605
2606 /* Check the dummy */
2607 model_check_dummy (model, root);
2608
2609 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "root");
2610 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "virtual-root");
2611}
2612
2613static void
2614mount_cb (GFile * file,
2615 GAsyncResult * res,
2616 MountInfo * mount_info)
2617{
2618 gboolean mounted;
2619 GError * error = NULL((void*)0);
2620 PlumaFileBrowserStore * model = mount_info->model;
2621
2622 mounted = g_file_mount_enclosing_volume_finish (file, res, &error);
2623
2624 if (mount_info->model)
2625 {
2626 model->priv->mount_info = NULL((void*)0);
2627 model_end_loading (model, model->priv->root);
2628 }
2629
2630 if (!mount_info->model || g_cancellable_is_cancelled (mount_info->cancellable))
2631 {
2632 // Reset because it might be reused?
2633 g_cancellable_reset (mount_info->cancellable);
2634 }
2635 else if (mounted)
2636 {
2637 model_root_mounted (model, mount_info->virtual_root);
2638 }
2639 else if (error->code != G_IO_ERROR_CANCELLED)
2640 {
2641 handle_root_error (model, error);
2642 }
2643
2644 if (error)
2645 g_error_free (error);
2646
2647 g_object_unref (mount_info->operation);
2648 g_object_unref (mount_info->cancellable);
2649 g_free (mount_info->virtual_root);
2650
2651 g_free (mount_info);
2652}
2653
2654static PlumaFileBrowserStoreResult
2655model_mount_root (PlumaFileBrowserStore * model, gchar const * virtual_root)
2656{
2657 GFileInfo * info;
2658 GError * error = NULL((void*)0);
2659 MountInfo * mount_info;
2660
2661 info = g_file_query_info (model->priv->root->file,
2662 G_FILE_ATTRIBUTE_STANDARD_TYPE"standard::type",
2663 G_FILE_QUERY_INFO_NONE,
2664 NULL((void*)0),
2665 &error);
2666
2667 if (!info) {
2668 if (error->code == G_IO_ERROR_NOT_MOUNTED) {
2669 /* Try to mount it */
2670 FILE_BROWSER_NODE_DIR (model->priv->root)((FileBrowserNodeDir *)(model->priv->root))->cancellable = g_cancellable_new ();
2671
2672 mount_info = g_new(MountInfo, 1)(MountInfo *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (MountInfo); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
2673 mount_info->model = model;
2674 mount_info->virtual_root = g_strdup (virtual_root)g_strdup_inline (virtual_root);
2675
2676 /* FIXME: we should be setting the correct window */
2677 mount_info->operation = gtk_mount_operation_new (NULL((void*)0));
2678 mount_info->cancellable = g_object_ref (FILE_BROWSER_NODE_DIR (model->priv->root)->cancellable)((__typeof__ (((FileBrowserNodeDir *)(model->priv->root
))->cancellable)) (g_object_ref) (((FileBrowserNodeDir *)(
model->priv->root))->cancellable))
;
2679
2680 model_begin_loading (model, model->priv->root);
2681 g_file_mount_enclosing_volume (model->priv->root->file,
2682 G_MOUNT_MOUNT_NONE,
2683 mount_info->operation,
2684 mount_info->cancellable,
2685 (GAsyncReadyCallback)mount_cb,
2686 mount_info);
2687
2688 model->priv->mount_info = mount_info;
2689 return PLUMA_FILE_BROWSER_STORE_RESULT_MOUNTING;
2690 }
2691 else
2692 {
2693 handle_root_error (model, error);
2694 }
2695
2696 g_error_free (error);
2697 } else {
2698 g_object_unref (info);
2699
2700 return model_root_mounted (model, virtual_root);
2701 }
2702
2703 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2704}
2705
2706/* Public */
2707PlumaFileBrowserStore *
2708pluma_file_browser_store_new (gchar const *root)
2709{
2710 PlumaFileBrowserStore *obj =
2711 PLUMA_FILE_BROWSER_STORE (g_object_new((((PlumaFileBrowserStore*) (void *) ((g_object_new ((pluma_file_browser_store_get_type
()), ((void*)0)))))))
2712 (PLUMA_TYPE_FILE_BROWSER_STORE,((((PlumaFileBrowserStore*) (void *) ((g_object_new ((pluma_file_browser_store_get_type
()), ((void*)0)))))))
2713 NULL))((((PlumaFileBrowserStore*) (void *) ((g_object_new ((pluma_file_browser_store_get_type
()), ((void*)0)))))))
;
2714
2715 pluma_file_browser_store_set_root (obj, root);
2716 return obj;
2717}
2718
2719void
2720pluma_file_browser_store_set_value (PlumaFileBrowserStore * tree_model,
2721 GtkTreeIter * iter, gint column,
2722 GValue * value)
2723{
2724 gpointer data;
2725 FileBrowserNode *node;
2726 GtkTreePath *path;
2727
2728 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (tree_model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_309
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((tree_model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_309 = 1; else _g_boolean_var_309 =
0; _g_boolean_var_309; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (tree_model)"
); return; } } while (0)
;
2729 g_return_if_fail (column ==do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_310
; if (column == PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM) _g_boolean_var_310
= 1; else _g_boolean_var_310 = 0; _g_boolean_var_310; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "column == PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM"
); return; } } while (0)
2730 PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_310
; if (column == PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM) _g_boolean_var_310
= 1; else _g_boolean_var_310 = 0; _g_boolean_var_310; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "column == PLUMA_FILE_BROWSER_STORE_COLUMN_EMBLEM"
); return; } } while (0)
;
2731 g_return_if_fail (G_VALUE_HOLDS_OBJECT (value))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_311
; if ((((__extension__ ({ const GValue *__val = (const GValue
*) ((value)); GType __t = (((GType) ((20) << (2)))); gboolean
__r; if (!__val) __r = (0); else if (__val->g_type == __t
) __r = (!(0)); else __r = g_type_check_value_holds (__val, __t
); __r; }))))) _g_boolean_var_311 = 1; else _g_boolean_var_311
= 0; _g_boolean_var_311; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "G_VALUE_HOLDS_OBJECT (value)"
); return; } } while (0)
;
2732 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_312
; if (iter != ((void*)0)) _g_boolean_var_312 = 1; else _g_boolean_var_312
= 0; _g_boolean_var_312; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
2733 g_return_if_fail (iter->user_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_313
; if (iter->user_data != ((void*)0)) _g_boolean_var_313 = 1
; else _g_boolean_var_313 = 0; _g_boolean_var_313; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return; } } while
(0)
;
2734
2735 data = g_value_get_object (value);
2736
2737 if (data)
2738 g_return_if_fail (GDK_IS_PIXBUF (data))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_314
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((data)); GType __t = ((gdk_pixbuf_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))) _g_boolean_var_314
= 1; else _g_boolean_var_314 = 0; _g_boolean_var_314; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "GDK_IS_PIXBUF (data)"); return; } } while
(0)
;
2739
2740 node = (FileBrowserNode *) (iter->user_data);
2741
2742 if (node->emblem)
2743 g_object_unref (node->emblem);
2744
2745 if (data)
2746 node->emblem = g_object_ref (GDK_PIXBUF (data))((__typeof__ (((((GdkPixbuf*) (void *) ((data))))))) (g_object_ref
) (((((GdkPixbuf*) (void *) ((data)))))))
;
2747 else
2748 node->emblem = NULL((void*)0);
2749
2750 model_recomposite_icon (tree_model, iter);
2751
2752 if (model_node_visibility (tree_model, node)) {
2753 path = pluma_file_browser_store_get_path (GTK_TREE_MODEL (tree_model)((((GtkTreeModel*) (void *) ((tree_model))))),
2754 iter);
2755 row_changed (tree_model, &path, iter);
2756 gtk_tree_path_free (path);
2757 }
2758}
2759
2760PlumaFileBrowserStoreResult
2761pluma_file_browser_store_set_virtual_root (PlumaFileBrowserStore * model,
2762 GtkTreeIter * iter)
2763{
2764 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_315
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_315 = 1; else _g_boolean_var_315 =
0; _g_boolean_var_315; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2765 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_315
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_315 = 1; else _g_boolean_var_315 =
0; _g_boolean_var_315; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2766 g_return_val_if_fail (iter != NULL,do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_316
; if (iter != ((void*)0)) _g_boolean_var_316 = 1; else _g_boolean_var_316
= 0; _g_boolean_var_316; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
(PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while (0)
2767 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_316
; if (iter != ((void*)0)) _g_boolean_var_316 = 1; else _g_boolean_var_316
= 0; _g_boolean_var_316; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
(PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while (0)
;
2768 g_return_val_if_fail (iter->user_data != NULL,do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_317
; if (iter->user_data != ((void*)0)) _g_boolean_var_317 = 1
; else _g_boolean_var_317 = 0; _g_boolean_var_317; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE
); } } while (0)
2769 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_317
; if (iter->user_data != ((void*)0)) _g_boolean_var_317 = 1
; else _g_boolean_var_317 = 0; _g_boolean_var_317; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE
); } } while (0)
;
2770
2771 model_clear (model, FALSE(0));
2772 set_virtual_root_from_node (model,
2773 (FileBrowserNode *) (iter->user_data));
2774
2775 return TRUE(!(0));
2776}
2777
2778PlumaFileBrowserStoreResult
2779pluma_file_browser_store_set_virtual_root_from_string
2780 (PlumaFileBrowserStore * model, gchar const *root) {
2781 GFile *file;
2782
2783 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_318
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_318 = 1; else _g_boolean_var_318 =
0; _g_boolean_var_318; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2784 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_318
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_318 = 1; else _g_boolean_var_318 =
0; _g_boolean_var_318; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2785
2786 file = g_file_new_for_uri (root);
2787 if (file == NULL((void*)0)) {
2788 g_warning ("Invalid uri (%s)", root);
2789 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2790 }
2791
2792 /* Check if uri is already the virtual root */
2793 if (model->priv->virtual_root &&
2794 g_file_equal (model->priv->virtual_root->file, file)) {
2795 g_object_unref (file);
2796 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2797 }
2798
2799 /* Check if uri is the root itself */
2800 if (g_file_equal (model->priv->root->file, file)) {
2801 g_object_unref (file);
2802
2803 /* Always clear the model before altering the nodes */
2804 model_clear (model, FALSE(0));
2805 set_virtual_root_from_node (model, model->priv->root);
2806 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2807 }
2808
2809 if (!g_file_has_prefix (file, model->priv->root->file)) {
2810 gchar *str, *str1;
2811
2812 str = g_file_get_parse_name (model->priv->root->file);
2813 str1 = g_file_get_parse_name (file);
2814
2815 g_warning
2816 ("Virtual root (%s) is not below actual root (%s)",
2817 str1, str);
2818
2819 g_free (str);
2820 g_free (str1);
2821
2822 g_object_unref (file);
2823 return PLUMA_FILE_BROWSER_STORE_RESULT_ERROR;
2824 }
2825
2826 set_virtual_root_from_file (model, file);
2827 g_object_unref (file);
2828
2829 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2830}
2831
2832PlumaFileBrowserStoreResult
2833pluma_file_browser_store_set_virtual_root_top (PlumaFileBrowserStore *
2834 model)
2835{
2836 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_319
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_319 = 1; else _g_boolean_var_319 =
0; _g_boolean_var_319; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2837 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_319
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_319 = 1; else _g_boolean_var_319 =
0; _g_boolean_var_319; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2838
2839 if (model->priv->virtual_root == model->priv->root)
2840 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2841
2842 model_clear (model, FALSE(0));
2843 set_virtual_root_from_node (model, model->priv->root);
2844
2845 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2846}
2847
2848PlumaFileBrowserStoreResult
2849pluma_file_browser_store_set_virtual_root_up (PlumaFileBrowserStore *
2850 model)
2851{
2852 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_320
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_320 = 1; else _g_boolean_var_320 =
0; _g_boolean_var_320; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2853 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_320
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_320 = 1; else _g_boolean_var_320 =
0; _g_boolean_var_320; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2854
2855 if (model->priv->virtual_root == model->priv->root)
2856 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2857
2858 model_clear (model, FALSE(0));
2859 set_virtual_root_from_node (model,
2860 model->priv->virtual_root->parent);
2861
2862 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2863}
2864
2865gboolean
2866pluma_file_browser_store_get_iter_virtual_root (PlumaFileBrowserStore *
2867 model, GtkTreeIter * iter)
2868{
2869 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_321
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_321 = 1; else _g_boolean_var_321 =
0; _g_boolean_var_321; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
2870 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_322
; if (iter != ((void*)0)) _g_boolean_var_322 = 1; else _g_boolean_var_322
= 0; _g_boolean_var_322; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
2871
2872 if (model->priv->virtual_root == NULL((void*)0))
2873 return FALSE(0);
2874
2875 iter->user_data = model->priv->virtual_root;
2876 return TRUE(!(0));
2877}
2878
2879gboolean
2880pluma_file_browser_store_get_iter_root (PlumaFileBrowserStore * model,
2881 GtkTreeIter * iter)
2882{
2883 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_323
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_323 = 1; else _g_boolean_var_323 =
0; _g_boolean_var_323; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
2884 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_324
; if (iter != ((void*)0)) _g_boolean_var_324 = 1; else _g_boolean_var_324
= 0; _g_boolean_var_324; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
2885
2886 if (model->priv->root == NULL((void*)0))
2887 return FALSE(0);
2888
2889 iter->user_data = model->priv->root;
2890 return TRUE(!(0));
2891}
2892
2893gboolean
2894pluma_file_browser_store_iter_equal (PlumaFileBrowserStore * model,
2895 GtkTreeIter * iter1,
2896 GtkTreeIter * iter2)
2897{
2898 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_325
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_325 = 1; else _g_boolean_var_325 =
0; _g_boolean_var_325; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
2899 g_return_val_if_fail (iter1 != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_326
; if (iter1 != ((void*)0)) _g_boolean_var_326 = 1; else _g_boolean_var_326
= 0; _g_boolean_var_326; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter1 != NULL");
return ((0)); } } while (0)
;
2900 g_return_val_if_fail (iter2 != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_327
; if (iter2 != ((void*)0)) _g_boolean_var_327 = 1; else _g_boolean_var_327
= 0; _g_boolean_var_327; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter2 != NULL");
return ((0)); } } while (0)
;
2901 g_return_val_if_fail (iter1->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_328
; if (iter1->user_data != ((void*)0)) _g_boolean_var_328 =
1; else _g_boolean_var_328 = 0; _g_boolean_var_328; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter1->user_data != NULL"); return ((0));
} } while (0)
;
2902 g_return_val_if_fail (iter2->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_329
; if (iter2->user_data != ((void*)0)) _g_boolean_var_329 =
1; else _g_boolean_var_329 = 0; _g_boolean_var_329; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter2->user_data != NULL"); return ((0));
} } while (0)
;
2903
2904 return (iter1->user_data == iter2->user_data);
2905}
2906
2907void
2908pluma_file_browser_store_cancel_mount_operation (PlumaFileBrowserStore *store)
2909{
2910 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (store))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_330
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((store)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_330 = 1; else _g_boolean_var_330 =
0; _g_boolean_var_330; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (store)"
); return; } } while (0)
;
2911
2912 cancel_mount_operation (store);
2913}
2914
2915PlumaFileBrowserStoreResult
2916pluma_file_browser_store_set_root_and_virtual_root (PlumaFileBrowserStore *
2917 model,
2918 gchar const *root,
2919 gchar const *virtual_root)
2920{
2921 GFile * file = NULL((void*)0);
2922 GFile * vfile = NULL((void*)0);
2923 FileBrowserNode * node;
2924 gboolean equal = FALSE(0);
2925
2926 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_331
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_331 = 1; else _g_boolean_var_331 =
0; _g_boolean_var_331; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2927 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_331
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_331 = 1; else _g_boolean_var_331 =
0; _g_boolean_var_331; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2928
2929 if (root == NULL((void*)0) && model->priv->root == NULL((void*)0))
2930 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2931
2932 if (root != NULL((void*)0)) {
2933 file = g_file_new_for_uri (root);
2934 }
2935
2936 if (root != NULL((void*)0) && model->priv->root != NULL((void*)0)) {
2937 equal = g_file_equal (file, model->priv->root->file);
2938
2939 if (equal && virtual_root == NULL((void*)0)) {
2940 g_object_unref (file);
2941 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2942 }
2943 }
2944
2945 if (virtual_root) {
2946 vfile = g_file_new_for_uri (virtual_root);
2947
2948 if (equal && g_file_equal (vfile, model->priv->virtual_root->file)) {
2949 if (file)
2950 g_object_unref (file);
2951
2952 g_object_unref (vfile);
2953 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
2954 }
2955
2956 g_object_unref (vfile);
2957 }
2958
2959 /* make sure to cancel any previous mount operations */
2960 cancel_mount_operation (model);
2961
2962 /* Always clear the model before altering the nodes */
2963 model_clear (model, TRUE(!(0)));
2964 file_browser_node_free (model, model->priv->root);
2965
2966 model->priv->root = NULL((void*)0);
2967 model->priv->virtual_root = NULL((void*)0);
2968
2969 if (file != NULL((void*)0)) {
2970 /* Create the root node */
2971 node = file_browser_node_dir_new (model, file, NULL((void*)0));
2972
2973 g_object_unref (file);
2974
2975 model->priv->root = node;
2976 return model_mount_root (model, virtual_root);
2977 } else {
2978 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "root");
2979 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "virtual-root");
2980 }
2981
2982 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
2983}
2984
2985PlumaFileBrowserStoreResult
2986pluma_file_browser_store_set_root (PlumaFileBrowserStore * model,
2987 gchar const *root)
2988{
2989 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_332
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_332 = 1; else _g_boolean_var_332 =
0; _g_boolean_var_332; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
2990 PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_332
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_332 = 1; else _g_boolean_var_332 =
0; _g_boolean_var_332; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
2991 return pluma_file_browser_store_set_root_and_virtual_root (model,
2992 root,
2993 NULL((void*)0));
2994}
2995
2996gchar *
2997pluma_file_browser_store_get_root (PlumaFileBrowserStore * model)
2998{
2999 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_333
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_333 = 1; else _g_boolean_var_333 =
0; _g_boolean_var_333; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (((void*)0)); } } while (0)
;
3000
3001 if (model->priv->root == NULL((void*)0) || model->priv->root->file == NULL((void*)0))
3002 return NULL((void*)0);
3003 else
3004 return g_file_get_uri (model->priv->root->file);
3005}
3006
3007gchar *
3008pluma_file_browser_store_get_virtual_root (PlumaFileBrowserStore * model)
3009{
3010 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_334
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_334 = 1; else _g_boolean_var_334 =
0; _g_boolean_var_334; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (((void*)0)); } } while (0)
;
3011
3012 if (model->priv->virtual_root == NULL((void*)0) || model->priv->virtual_root->file == NULL((void*)0))
3013 return NULL((void*)0);
3014 else
3015 return g_file_get_uri (model->priv->virtual_root->file);
3016}
3017
3018void
3019_pluma_file_browser_store_iter_expanded (PlumaFileBrowserStore * model,
3020 GtkTreeIter * iter)
3021{
3022 FileBrowserNode *node;
3023
3024 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_335
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_335 = 1; else _g_boolean_var_335 =
0; _g_boolean_var_335; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return; } } while (0)
;
3025 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_336
; if (iter != ((void*)0)) _g_boolean_var_336 = 1; else _g_boolean_var_336
= 0; _g_boolean_var_336; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
3026 g_return_if_fail (iter->user_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_337
; if (iter->user_data != ((void*)0)) _g_boolean_var_337 = 1
; else _g_boolean_var_337 = 0; _g_boolean_var_337; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return; } } while
(0)
;
3027
3028 node = (FileBrowserNode *) (iter->user_data);
3029
3030 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
&& !NODE_LOADED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
) {
3031 /* Load it now */
3032 model_load_directory (model, node);
3033 }
3034}
3035
3036void
3037_pluma_file_browser_store_iter_collapsed (PlumaFileBrowserStore * model,
3038 GtkTreeIter * iter)
3039{
3040 FileBrowserNode *node;
3041 GSList *item;
3042
3043 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_338
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_338 = 1; else _g_boolean_var_338 =
0; _g_boolean_var_338; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return; } } while (0)
;
3044 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_339
; if (iter != ((void*)0)) _g_boolean_var_339 = 1; else _g_boolean_var_339
= 0; _g_boolean_var_339; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
3045 g_return_if_fail (iter->user_data != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_340
; if (iter->user_data != ((void*)0)) _g_boolean_var_340 = 1
; else _g_boolean_var_340 = 0; _g_boolean_var_340; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return; } } while
(0)
;
3046
3047 node = (FileBrowserNode *) (iter->user_data);
3048
3049 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
&& NODE_LOADED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
) {
3050 /* Unload children of the children, keeping 1 depth in cache */
3051
3052 for (item = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node))->children; item;
3053 item = item->next) {
3054 node = (FileBrowserNode *) (item->data);
3055
3056 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
&& NODE_LOADED (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_LOADED
))
) {
3057 file_browser_node_unload (model, node,
3058 TRUE(!(0)));
3059 model_check_dummy (model, node);
3060 }
3061 }
3062 }
3063}
3064
3065PlumaFileBrowserStoreFilterMode
3066pluma_file_browser_store_get_filter_mode (PlumaFileBrowserStore * model)
3067{
3068 return model->priv->filter_mode;
3069}
3070
3071void
3072pluma_file_browser_store_set_filter_mode (PlumaFileBrowserStore * model,
3073 PlumaFileBrowserStoreFilterMode
3074 mode)
3075{
3076 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_341
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_341 = 1; else _g_boolean_var_341 =
0; _g_boolean_var_341; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return; } } while (0)
;
3077
3078 if (model->priv->filter_mode == mode)
3079 return;
3080
3081 model->priv->filter_mode = mode;
3082 model_refilter (model);
3083
3084 g_object_notify (G_OBJECT (model)((((GObject*) (void *) ((model))))), "filter-mode");
3085}
3086
3087void
3088pluma_file_browser_store_set_filter_func (PlumaFileBrowserStore * model,
3089 PlumaFileBrowserStoreFilterFunc
3090 func, gpointer user_data)
3091{
3092 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_342
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_342 = 1; else _g_boolean_var_342 =
0; _g_boolean_var_342; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return; } } while (0)
;
3093
3094 model->priv->filter_func = func;
3095 model->priv->filter_user_data = user_data;
3096 model_refilter (model);
3097}
3098
3099void
3100pluma_file_browser_store_refilter (PlumaFileBrowserStore * model)
3101{
3102 model_refilter (model);
3103}
3104
3105PlumaFileBrowserStoreFilterMode
3106pluma_file_browser_store_filter_mode_get_default (void)
3107{
3108 return PLUMA_FILE_BROWSER_STORE_FILTER_MODE_HIDE_HIDDEN;
3109}
3110
3111void
3112pluma_file_browser_store_refresh (PlumaFileBrowserStore * model)
3113{
3114 g_return_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_343
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_343 = 1; else _g_boolean_var_343 =
0; _g_boolean_var_343; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return; } } while (0)
;
3115
3116 if (model->priv->root == NULL((void*)0) || model->priv->virtual_root == NULL((void*)0))
3117 return;
3118
3119 /* Clear the model */
3120 g_signal_emit (model, model_signals[BEGIN_REFRESH], 0);
3121 file_browser_node_unload (model, model->priv->virtual_root, TRUE(!(0)));
3122 model_load_directory (model, model->priv->virtual_root);
3123 g_signal_emit (model, model_signals[END_REFRESH], 0);
3124}
3125
3126static void
3127reparent_node (FileBrowserNode * node, gboolean reparent)
3128{
3129 FileBrowserNodeDir * dir;
3130 GSList * child;
3131 GFile * parent;
3132 gchar * base;
3133
3134 if (!node->file) {
3135 return;
3136 }
3137
3138 if (reparent) {
3139 parent = node->parent->file;
3140 base = g_file_get_basename (node->file);
3141 g_object_unref (node->file);
3142
3143 node->file = g_file_get_child (parent, base);
3144 g_free (base);
3145 }
3146
3147 if (NODE_IS_DIR (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY
))
) {
3148 dir = FILE_BROWSER_NODE_DIR (node)((FileBrowserNodeDir *)(node));
3149
3150 for (child = dir->children; child; child = child->next) {
3151 reparent_node ((FileBrowserNode *)child->data, TRUE(!(0)));
3152 }
3153 }
3154}
3155
3156gboolean
3157pluma_file_browser_store_rename (PlumaFileBrowserStore * model,
3158 GtkTreeIter * iter,
3159 const gchar * new_name,
3160 GError ** error)
3161{
3162 FileBrowserNode *node;
3163 GFile * file;
3164 GFile * parent;
3165 GFile * previous;
3166 GError * err = NULL((void*)0);
3167 gchar * olduri;
3168 gchar * newuri;
3169 GtkTreePath *path;
3170
3171 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_344
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_344 = 1; else _g_boolean_var_344 =
0; _g_boolean_var_344; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
3172 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_345
; if (iter != ((void*)0)) _g_boolean_var_345 = 1; else _g_boolean_var_345
= 0; _g_boolean_var_345; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
3173 g_return_val_if_fail (iter->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_346
; if (iter->user_data != ((void*)0)) _g_boolean_var_346 = 1
; else _g_boolean_var_346 = 0; _g_boolean_var_346; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return ((0)); }
} while (0)
;
3174
3175 node = (FileBrowserNode *) (iter->user_data);
3176
3177 parent = g_file_get_parent (node->file);
3178 g_return_val_if_fail (parent != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_347
; if (parent != ((void*)0)) _g_boolean_var_347 = 1; else _g_boolean_var_347
= 0; _g_boolean_var_347; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "parent != NULL")
; return ((0)); } } while (0)
;
3179
3180 file = g_file_get_child (parent, new_name);
3181 g_object_unref (parent);
3182
3183 if (g_file_equal (node->file, file)) {
3184 g_object_unref (file);
3185 return TRUE(!(0));
3186 }
3187
3188 if (g_file_move (node->file, file, G_FILE_COPY_NONE, NULL((void*)0), NULL((void*)0), NULL((void*)0), &err)) {
3189 previous = node->file;
3190 node->file = file;
3191
3192 /* This makes sure the actual info for the node is requeried */
3193 file_browser_node_set_name (node);
3194 file_browser_node_set_from_info (model, node, NULL((void*)0), TRUE(!(0)));
3195
3196 reparent_node (node, FALSE(0));
3197
3198 if (model_node_visibility (model, node)) {
3199 path = pluma_file_browser_store_get_path_real (model, node);
3200 row_changed (model, &path, iter);
3201 gtk_tree_path_free (path);
3202
3203 /* Reorder this item */
3204 model_resort_node (model, node);
3205 } else {
3206 g_object_unref (previous);
3207
3208 if (error != NULL((void*)0))
3209 *error = g_error_new_literal (pluma_file_browser_store_error_quark (),
3210 PLUMA_FILE_BROWSER_ERROR_RENAME,
3211 _("The renamed file is currently filtered out. You need to adjust your filter settings to make the file visible")((char *) g_dgettext ("pluma", "The renamed file is currently filtered out. You need to adjust your filter settings to make the file visible"
))
);
3212 return FALSE(0);
3213 }
3214
3215 olduri = g_file_get_uri (previous);
3216 newuri = g_file_get_uri (node->file);
3217
3218 g_signal_emit (model, model_signals[RENAME], 0, olduri, newuri);
3219
3220 g_object_unref (previous);
3221 g_free (olduri);
3222 g_free (newuri);
3223
3224 return TRUE(!(0));
3225 } else {
3226 g_object_unref (file);
3227
3228 if (err) {
3229 if (error != NULL((void*)0)) {
3230 *error =
3231 g_error_new_literal
3232 (pluma_file_browser_store_error_quark (),
3233 PLUMA_FILE_BROWSER_ERROR_RENAME,
3234 err->message);
3235 }
3236
3237 g_error_free (err);
3238 }
3239
3240 return FALSE(0);
3241 }
3242}
3243
3244static void
3245async_data_free (AsyncData * data)
3246{
3247 g_object_unref (data->cancellable);
3248
3249 g_list_free_full (data->files, g_object_unref);
3250
3251 if (!data->removed)
3252 data->model->priv->async_handles = g_slist_remove (data->model->priv->async_handles, data);
3253
3254 g_free (data);
3255}
3256
3257static gboolean
3258emit_no_trash (AsyncData * data)
3259{
3260 /* Emit the no trash error */
3261 gboolean ret;
3262
3263 g_signal_emit (data->model, model_signals[NO_TRASH], 0, data->files, &ret);
3264 return ret;
3265}
3266
3267static void
3268delete_file_finished (GFile *file,
3269 GAsyncResult *res,
3270 AsyncData *data)
3271{
3272 GError * error = NULL((void*)0);
3273 gboolean ok;
3274
3275 if (data->trash)
3276 {
3277 ok = g_file_trash_finish (file, res, &error);
3278 }
3279 else
3280 {
3281 ok = g_file_delete_finish (file, res, &error);
3282 }
3283
3284 if (ok)
3285 {
3286 /* Remove the file from the model */
3287 FileBrowserNode *node = model_find_node (data->model, NULL((void*)0), file);
3288
3289 if (node != NULL((void*)0))
3290 {
3291 model_remove_node (data->model, node, NULL((void*)0), TRUE(!(0)));
3292 }
3293
3294 /* Process the next file */
3295 data->iter = data->iter->next;
3296 }
3297 else if (!ok && error != NULL((void*)0))
3298 {
3299 gint code = error->code;
3300 g_error_free (error);
3301
3302 if (data->trash && code == G_IO_ERROR_NOT_SUPPORTED) {
3303 /* Trash is not supported on this system. Ask the user
3304 * if he wants to delete completely the files instead.
3305 */
3306 if (emit_no_trash (data))
3307 {
3308 /* Changes this into a delete job */
3309 data->trash = FALSE(0);
3310 data->iter = data->files;
3311 }
3312 else
3313 {
3314 /* End the job */
3315 async_data_free (data);
3316 return;
3317 }
3318 }
3319 else if (code == G_IO_ERROR_CANCELLED)
3320 {
3321 /* Job has been cancelled, end the job */
3322 async_data_free (data);
3323 return;
3324 }
3325 }
3326
3327 /* Continue the job */
3328 delete_files (data);
3329}
3330
3331static void
3332delete_files (AsyncData *data)
3333{
3334 GFile *file;
3335
3336 /* Check if our job is done */
3337 if (data->iter == NULL((void*)0))
3338 {
3339 async_data_free (data);
3340 return;
3341 }
3342
3343 file = G_FILE (data->iter->data)((((GFile*) (void *) ((data->iter->data)))));
3344
3345 if (data->trash)
3346 {
3347 g_file_trash_async (file,
3348 G_PRIORITY_DEFAULT0,
3349 data->cancellable,
3350 (GAsyncReadyCallback)delete_file_finished,
3351 data);
3352 }
3353 else
3354 {
3355 g_file_delete_async (file,
3356 G_PRIORITY_DEFAULT0,
3357 data->cancellable,
3358 (GAsyncReadyCallback)delete_file_finished,
3359 data);
3360 }
3361}
3362
3363PlumaFileBrowserStoreResult
3364pluma_file_browser_store_delete_all (PlumaFileBrowserStore *model,
3365 GList *rows, gboolean trash)
3366{
3367 FileBrowserNode * node;
3368 AsyncData * data;
3369 GList * files = NULL((void*)0);
3370 GList * row;
3371 GtkTreeIter iter;
3372 GtkTreePath * prev = NULL((void*)0);
3373 GtkTreePath * path;
3374
3375 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_348
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_348 = 1; else _g_boolean_var_348 =
0; _g_boolean_var_348; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
3376
3377 if (rows == NULL((void*)0))
3378 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
3379
3380 /* First we sort the paths so that we can later on remove any
3381 files/directories that are actually subfiles/directories of
3382 a directory that's also deleted */
3383 rows = g_list_sort (g_list_copy (rows), (GCompareFunc)gtk_tree_path_compare);
3384
3385 for (row = rows; row; row = row->next) {
3386 path = (GtkTreePath *)(row->data);
3387
3388 if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (model)((((GtkTreeModel*) (void *) ((model))))), &iter, path))
3389 continue;
3390
3391 /* Skip if the current path is actually a descendant of the
3392 previous path */
3393 if (prev != NULL((void*)0) && gtk_tree_path_is_descendant (path, prev))
3394 continue;
3395
3396 prev = path;
3397 node = (FileBrowserNode *)(iter.user_data);
3398 files = g_list_prepend (files, g_object_ref (node->file)((__typeof__ (node->file)) (g_object_ref) (node->file)));
3399 }
3400
3401 data = g_new (AsyncData, 1)(AsyncData *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (AsyncData); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
3402
3403 data->model = model;
3404 data->cancellable = g_cancellable_new ();
3405 data->files = files;
3406 data->trash = trash;
3407 data->iter = files;
3408 data->removed = FALSE(0);
3409
3410 model->priv->async_handles =
3411 g_slist_prepend (model->priv->async_handles, data);
3412
3413 delete_files (data);
3414 g_list_free (rows);
3415
3416 return PLUMA_FILE_BROWSER_STORE_RESULT_OK;
3417}
3418
3419PlumaFileBrowserStoreResult
3420pluma_file_browser_store_delete (PlumaFileBrowserStore * model,
3421 GtkTreeIter * iter, gboolean trash)
3422{
3423 FileBrowserNode *node;
3424 GList *rows = NULL((void*)0);
3425 PlumaFileBrowserStoreResult result;
3426
3427 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_349
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_349 = 1; else _g_boolean_var_349 =
0; _g_boolean_var_349; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while
(0)
;
3428 g_return_val_if_fail (iter != NULL, PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_350
; if (iter != ((void*)0)) _g_boolean_var_350 = 1; else _g_boolean_var_350
= 0; _g_boolean_var_350; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
(PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE); } } while (0)
;
3429 g_return_val_if_fail (iter->user_data != NULL, PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_351
; if (iter->user_data != ((void*)0)) _g_boolean_var_351 = 1
; else _g_boolean_var_351 = 0; _g_boolean_var_351; }), 1))) {
} else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "iter->user_data != NULL"); return (PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE
); } } while (0)
;
3430
3431 node = (FileBrowserNode *) (iter->user_data);
3432
3433 if (NODE_IS_DUMMY (node)(((node)->flags & PLUMA_FILE_BROWSER_STORE_FLAG_IS_DUMMY
))
)
3434 return PLUMA_FILE_BROWSER_STORE_RESULT_NO_CHANGE;
3435
3436 rows = g_list_append(NULL((void*)0), pluma_file_browser_store_get_path_real (model, node));
3437 result = pluma_file_browser_store_delete_all (model, rows, trash);
3438
3439 g_list_free_full (rows, (GDestroyNotify) gtk_tree_path_free);
3440
3441 return result;
3442}
3443
3444gboolean
3445pluma_file_browser_store_new_file (PlumaFileBrowserStore * model,
3446 GtkTreeIter * parent,
3447 GtkTreeIter * iter)
3448{
3449 GFile * file;
3450 GFileOutputStream * stream;
3451 FileBrowserNodeDir *parent_node;
3452 gboolean result = FALSE(0);
3453 FileBrowserNode *node;
3454 GError * error = NULL((void*)0);
3455
3456 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_352
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_352 = 1; else _g_boolean_var_352 =
0; _g_boolean_var_352; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
3457 g_return_val_if_fail (parent != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_353
; if (parent != ((void*)0)) _g_boolean_var_353 = 1; else _g_boolean_var_353
= 0; _g_boolean_var_353; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "parent != NULL")
; return ((0)); } } while (0)
;
3458 g_return_val_if_fail (parent->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_354
; if (parent->user_data != ((void*)0)) _g_boolean_var_354 =
1; else _g_boolean_var_354 = 0; _g_boolean_var_354; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "parent->user_data != NULL"); return ((0))
; } } while (0)
;
3459 g_return_val_if_fail (NODE_IS_DIRdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_355
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_355
= 1; else _g_boolean_var_355 = 0; _g_boolean_var_355; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
3460 ((FileBrowserNode *) (parent->user_data)),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_355
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_355
= 1; else _g_boolean_var_355 = 0; _g_boolean_var_355; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
3461 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_355
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_355
= 1; else _g_boolean_var_355 = 0; _g_boolean_var_355; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
;
3462 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_356
; if (iter != ((void*)0)) _g_boolean_var_356 = 1; else _g_boolean_var_356
= 0; _g_boolean_var_356; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
3463
3464 parent_node = FILE_BROWSER_NODE_DIR (parent->user_data)((FileBrowserNodeDir *)(parent->user_data));
3465 /* Translators: This is the default name of new files created by the file browser pane. */
3466 file = unique_new_name (((FileBrowserNode *) parent_node)->file, _("file")((char *) g_dgettext ("pluma", "file")));
3467
3468 stream = g_file_create (file, G_FILE_CREATE_NONE, NULL((void*)0), &error);
3469
3470 if (!stream)
3471 {
3472 g_signal_emit (model, model_signals[ERROR], 0,
3473 PLUMA_FILE_BROWSER_ERROR_NEW_FILE,
3474 error->message);
3475 g_error_free (error);
3476 } else {
3477 g_object_unref (stream);
3478 node = model_add_node_from_file (model,
3479 (FileBrowserNode *)parent_node,
3480 file,
3481 NULL((void*)0));
3482
3483 if (model_node_visibility (model, node)) {
3484 iter->user_data = node;
3485 result = TRUE(!(0));
3486 } else {
3487 g_signal_emit (model, model_signals[ERROR], 0,
3488 PLUMA_FILE_BROWSER_ERROR_NEW_FILE,
3489 _((char *) g_dgettext ("pluma", "The new file is currently filtered out. You need to adjust your filter settings to make the file visible"
))
3490 ("The new file is currently filtered out. You need to adjust your filter settings to make the file visible")((char *) g_dgettext ("pluma", "The new file is currently filtered out. You need to adjust your filter settings to make the file visible"
))
);
3491 }
3492 }
3493
3494 g_object_unref (file);
3495 return result;
3496}
3497
3498gboolean
3499pluma_file_browser_store_new_directory (PlumaFileBrowserStore * model,
3500 GtkTreeIter * parent,
3501 GtkTreeIter * iter)
3502{
3503 GFile * file;
3504 FileBrowserNodeDir *parent_node;
3505 GError * error = NULL((void*)0);
3506 FileBrowserNode *node;
3507 gboolean result = FALSE(0);
3508
3509 g_return_val_if_fail (PLUMA_IS_FILE_BROWSER_STORE (model), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_357
; if ((((__extension__ ({ GTypeInstance *__inst = (GTypeInstance
*) ((model)); GType __t = ((pluma_file_browser_store_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))) _g_boolean_var_357 = 1; else _g_boolean_var_357 =
0; _g_boolean_var_357; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "PLUMA_IS_FILE_BROWSER_STORE (model)"
); return ((0)); } } while (0)
;
3510 g_return_val_if_fail (parent != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_358
; if (parent != ((void*)0)) _g_boolean_var_358 = 1; else _g_boolean_var_358
= 0; _g_boolean_var_358; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "parent != NULL")
; return ((0)); } } while (0)
;
3511 g_return_val_if_fail (parent->user_data != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_359
; if (parent->user_data != ((void*)0)) _g_boolean_var_359 =
1; else _g_boolean_var_359 = 0; _g_boolean_var_359; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "parent->user_data != NULL"); return ((0))
; } } while (0)
;
3512 g_return_val_if_fail (NODE_IS_DIRdo { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_360
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_360
= 1; else _g_boolean_var_360 = 0; _g_boolean_var_360; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
3513 ((FileBrowserNode *) (parent->user_data)),do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_360
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_360
= 1; else _g_boolean_var_360 = 0; _g_boolean_var_360; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
3514 FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_360
; if (((((FileBrowserNode *) (parent->user_data))->flags
& PLUMA_FILE_BROWSER_STORE_FLAG_IS_DIRECTORY))) _g_boolean_var_360
= 1; else _g_boolean_var_360 = 0; _g_boolean_var_360; }), 1)
)) { } else { g_return_if_fail_warning (((gchar*) 0), ((const
char*) (__func__)), "NODE_IS_DIR ((FileBrowserNode *) (parent->user_data))"
); return ((0)); } } while (0)
;
3515 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_361
; if (iter != ((void*)0)) _g_boolean_var_361 = 1; else _g_boolean_var_361
= 0; _g_boolean_var_361; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
3516
3517 parent_node = FILE_BROWSER_NODE_DIR (parent->user_data)((FileBrowserNodeDir *)(parent->user_data));
3518 /* Translators: This is the default name of new directories created by the file browser pane. */
3519 file = unique_new_name (((FileBrowserNode *) parent_node)->file, _("directory")((char *) g_dgettext ("pluma", "directory")));
3520
3521 if (!g_file_make_directory (file, NULL((void*)0), &error)) {
3522 g_signal_emit (model, model_signals[ERROR], 0,
3523 PLUMA_FILE_BROWSER_ERROR_NEW_DIRECTORY,
3524 error->message);
3525 g_error_free (error);
3526 } else {
3527 node = model_add_node_from_file (model,
3528 (FileBrowserNode *)parent_node,
3529 file,
3530 NULL((void*)0));
3531
3532 if (model_node_visibility (model, node)) {
3533 iter->user_data = node;
3534 result = TRUE(!(0));
3535 } else {
3536 g_signal_emit (model, model_signals[ERROR], 0,
3537 PLUMA_FILE_BROWSER_ERROR_NEW_FILE,
3538 _((char *) g_dgettext ("pluma", "The new directory is currently filtered out. You need to adjust your filter settings to make the directory visible"
))
3539 ("The new directory is currently filtered out. You need to adjust your filter settings to make the directory visible")((char *) g_dgettext ("pluma", "The new directory is currently filtered out. You need to adjust your filter settings to make the directory visible"
))
);
3540 }
3541 }
3542
3543 g_object_unref (file);
3544 return result;
3545}
3546
3547void
3548_pluma_file_browser_store_register_type (GTypeModule *type_module)
3549{
3550 pluma_file_browser_store_register_type (type_module);
3551}
3552
3553// ex:ts=8:noet:
diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-a608c3.html b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-a608c3.html new file mode 100644 index 00000000..14bd19ed --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-a608c3.html @@ -0,0 +1,1327 @@ + + + +plumatextregion.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:pluma/plumatextregion.c
Warning:line 265, column 4
Value stored to 'l' is never read
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name plumatextregion.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/pluma -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I .. -I . -I ./mate-submodules/libegg -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/gtksourceview-4 -I /usr/include/libpeas-1.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D DATADIR="/usr/local/share" -D PLUMA_DATADIR="/usr/local/share/pluma" -D PLUMA_LOCALEDIR="/usr/local/share/locale/" -D LIBDIR="/usr/local/lib" -D PLUMA_LIBDIR="/usr/local/lib/pluma" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/pluma -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-10-22-114445-13211-1 -x c plumatextregion.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2 *
3 * plumatextregion.h - GtkTextMark based region utility functions
4 *
5 * This file is part of the GtkSourceView widget
6 *
7 * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez@gmx.net>
8 * Copyright (C) 2012-2021 MATE Developers
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
24 */
25
26#ifdef HAVE_CONFIG_H1
27#include <config.h>
28#endif
29
30#include <glib.h>
31
32#include "plumatextregion.h"
33
34
35#undef ENABLE_DEBUG
36/*
37#define ENABLE_DEBUG
38*/
39
40#ifdef ENABLE_DEBUG
41#define DEBUG(x) (x)
42#else
43#define DEBUG(x)
44#endif
45
46typedef struct _Subregion {
47 GtkTextMark *start;
48 GtkTextMark *end;
49} Subregion;
50
51struct _PlumaTextRegion {
52 GtkTextBuffer *buffer;
53 GList *subregions;
54 guint32 time_stamp;
55};
56
57typedef struct _PlumaTextRegionIteratorReal PlumaTextRegionIteratorReal;
58
59struct _PlumaTextRegionIteratorReal {
60 PlumaTextRegion *region;
61 guint32 region_time_stamp;
62
63 GList *subregions;
64};
65
66
67/* ----------------------------------------------------------------------
68 Private interface
69 ---------------------------------------------------------------------- */
70
71/* Find and return a subregion node which contains the given text
72 iter. If left_side is TRUE, return the subregion which contains
73 the text iter or which is the leftmost; else return the rightmost
74 subregion */
75static GList *
76find_nearest_subregion (PlumaTextRegion *region,
77 const GtkTextIter *iter,
78 GList *begin,
79 gboolean leftmost,
80 gboolean include_edges)
81{
82 GList *l, *retval;
83
84 g_return_val_if_fail (region != NULL && iter != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_31
; if (region != ((void*)0) && iter != ((void*)0)) _g_boolean_var_31
= 1; else _g_boolean_var_31 = 0; _g_boolean_var_31; }), 1)))
{ } else { g_return_if_fail_warning (((gchar*) 0), ((const char
*) (__func__)), "region != NULL && iter != NULL"); return
(((void*)0)); } } while (0)
;
85
86 if (!begin)
87 begin = region->subregions;
88
89 if (begin)
90 retval = begin->prev;
91 else
92 retval = NULL((void*)0);
93
94 for (l = begin; l; l = l->next) {
95 GtkTextIter sr_iter;
96 Subregion *sr = l->data;
97 gint cmp;
98
99 if (!leftmost) {
100 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_iter, sr->end);
101 cmp = gtk_text_iter_compare (iter, &sr_iter);
102 if (cmp < 0 || (cmp == 0 && include_edges)) {
103 retval = l;
104 break;
105 }
106
107 } else {
108 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_iter, sr->start);
109 cmp = gtk_text_iter_compare (iter, &sr_iter);
110 if (cmp > 0 || (cmp == 0 && include_edges))
111 retval = l;
112 else
113 break;
114 }
115 }
116 return retval;
117}
118
119/* ----------------------------------------------------------------------
120 Public interface
121 ---------------------------------------------------------------------- */
122
123PlumaTextRegion *
124pluma_text_region_new (GtkTextBuffer *buffer)
125{
126 PlumaTextRegion *region;
127
128 g_return_val_if_fail (buffer != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_32
; if (buffer != ((void*)0)) _g_boolean_var_32 = 1; else _g_boolean_var_32
= 0; _g_boolean_var_32; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "buffer != NULL")
; return (((void*)0)); } } while (0)
;
129
130 region = g_new (PlumaTextRegion, 1)(PlumaTextRegion *) (__extension__ ({ gsize __n = (gsize) (1)
; gsize __s = sizeof (PlumaTextRegion); gpointer __p; if (__s
== 1) __p = g_malloc (__n); else if (__builtin_constant_p (__n
) && (__s == 0 || __n <= (9223372036854775807L *2UL
+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
131 region->buffer = buffer;
132 region->subregions = NULL((void*)0);
133 region->time_stamp = 0;
134
135 return region;
136}
137
138void
139pluma_text_region_destroy (PlumaTextRegion *region, gboolean delete_marks)
140{
141 g_return_if_fail (region != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_33
; if (region != ((void*)0)) _g_boolean_var_33 = 1; else _g_boolean_var_33
= 0; _g_boolean_var_33; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return; } } while (0)
;
142
143 while (region->subregions) {
144 Subregion *sr = region->subregions->data;
145 if (delete_marks) {
146 gtk_text_buffer_delete_mark (region->buffer, sr->start);
147 gtk_text_buffer_delete_mark (region->buffer, sr->end);
148 }
149 g_free (sr);
150 region->subregions = g_list_delete_link (region->subregions,
151 region->subregions);
152 }
153 region->buffer = NULL((void*)0);
154 region->time_stamp = 0;
155
156 g_free (region);
157}
158
159GtkTextBuffer *
160pluma_text_region_get_buffer (PlumaTextRegion *region)
161{
162 g_return_val_if_fail (region != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_34
; if (region != ((void*)0)) _g_boolean_var_34 = 1; else _g_boolean_var_34
= 0; _g_boolean_var_34; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return (((void*)0)); } } while (0)
;
163
164 return region->buffer;
165}
166
167static void
168pluma_text_region_clear_zero_length_subregions (PlumaTextRegion *region)
169{
170 GtkTextIter start, end;
171 GList *node;
172
173 g_return_if_fail (region != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_35
; if (region != ((void*)0)) _g_boolean_var_35 = 1; else _g_boolean_var_35
= 0; _g_boolean_var_35; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return; } } while (0)
;
174
175 for (node = region->subregions; node; ) {
176 Subregion *sr = node->data;
177 gtk_text_buffer_get_iter_at_mark (region->buffer, &start, sr->start);
178 gtk_text_buffer_get_iter_at_mark (region->buffer, &end, sr->end);
179 if (gtk_text_iter_equal (&start, &end)) {
180 gtk_text_buffer_delete_mark (region->buffer, sr->start);
181 gtk_text_buffer_delete_mark (region->buffer, sr->end);
182 g_free (sr);
183 if (node == region->subregions)
184 region->subregions = node = g_list_delete_link (node, node);
185 else
186 node = g_list_delete_link (node, node);
187
188 ++region->time_stamp;
189
190 } else {
191 node = node->next;
192 }
193 }
194}
195
196void
197pluma_text_region_add (PlumaTextRegion *region,
198 const GtkTextIter *_start,
199 const GtkTextIter *_end)
200{
201 GList *start_node, *end_node;
202 GtkTextIter start, end;
203
204 g_return_if_fail (region != NULL && _start != NULL && _end != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_36
; if (region != ((void*)0) && _start != ((void*)0) &&
_end != ((void*)0)) _g_boolean_var_36 = 1; else _g_boolean_var_36
= 0; _g_boolean_var_36; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL && _start != NULL && _end != NULL"
); return; } } while (0)
;
205
206 start = *_start;
207 end = *_end;
208
209 DEBUG (g_print ("---\n"));
210 DEBUG (pluma_text_region_debug_print (region));
211 DEBUG (g_message ("region_add (%d, %d)",
212 gtk_text_iter_get_offset (&start),
213 gtk_text_iter_get_offset (&end)));
214
215 gtk_text_iter_order (&start, &end);
216
217 /* don't add zero-length regions */
218 if (gtk_text_iter_equal (&start, &end))
219 return;
220
221 /* find bounding subregions */
222 start_node = find_nearest_subregion (region, &start, NULL((void*)0), FALSE(0), TRUE(!(0)));
223 end_node = find_nearest_subregion (region, &end, start_node, TRUE(!(0)), TRUE(!(0)));
224
225 if (start_node == NULL((void*)0) || end_node == NULL((void*)0) || end_node == start_node->prev) {
226 /* create the new subregion */
227 Subregion *sr = g_new0 (Subregion, 1)(Subregion *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (Subregion); gpointer __p; if (__s == 1) __p = g_malloc0
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s); __p
; }))
;
228 sr->start = gtk_text_buffer_create_mark (region->buffer, NULL((void*)0), &start, TRUE(!(0)));
229 sr->end = gtk_text_buffer_create_mark (region->buffer, NULL((void*)0), &end, FALSE(0));
230
231 if (start_node == NULL((void*)0)) {
232 /* append the new region */
233 region->subregions = g_list_append (region->subregions, sr);
234
235 } else if (end_node == NULL((void*)0)) {
236 /* prepend the new region */
237 region->subregions = g_list_prepend (region->subregions, sr);
238
239 } else {
240 /* we are in the middle of two subregions */
241 region->subregions = g_list_insert_before (region->subregions,
242 start_node, sr);
243 }
244 }
245 else {
246 GtkTextIter iter;
247 Subregion *sr = start_node->data;
248 if (start_node != end_node) {
249 /* we need to merge some subregions */
250 GList *l = start_node->next;
251 Subregion *q;
252
253 gtk_text_buffer_delete_mark (region->buffer, sr->end);
254 while (l != end_node) {
255 q = l->data;
256 gtk_text_buffer_delete_mark (region->buffer, q->start);
257 gtk_text_buffer_delete_mark (region->buffer, q->end);
258 g_free (q);
259 l = g_list_delete_link (l, l);
260 }
261 q = l->data;
262 gtk_text_buffer_delete_mark (region->buffer, q->start);
263 sr->end = q->end;
264 g_free (q);
265 l = g_list_delete_link (l, l);
Value stored to 'l' is never read
266 }
267 /* now move marks if that action expands the region */
268 gtk_text_buffer_get_iter_at_mark (region->buffer, &iter, sr->start);
269 if (gtk_text_iter_compare (&iter, &start) > 0)
270 gtk_text_buffer_move_mark (region->buffer, sr->start, &start);
271 gtk_text_buffer_get_iter_at_mark (region->buffer, &iter, sr->end);
272 if (gtk_text_iter_compare (&iter, &end) < 0)
273 gtk_text_buffer_move_mark (region->buffer, sr->end, &end);
274 }
275
276 ++region->time_stamp;
277
278 DEBUG (pluma_text_region_debug_print (region));
279}
280
281void
282pluma_text_region_subtract (PlumaTextRegion *region,
283 const GtkTextIter *_start,
284 const GtkTextIter *_end)
285{
286 GList *start_node, *end_node, *node;
287 GtkTextIter sr_start_iter, sr_end_iter;
288 gboolean done;
289 gboolean start_is_outside, end_is_outside;
290 Subregion *sr;
291 GtkTextIter start, end;
292
293 g_return_if_fail (region != NULL && _start != NULL && _end != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_37
; if (region != ((void*)0) && _start != ((void*)0) &&
_end != ((void*)0)) _g_boolean_var_37 = 1; else _g_boolean_var_37
= 0; _g_boolean_var_37; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL && _start != NULL && _end != NULL"
); return; } } while (0)
;
294
295 start = *_start;
296 end = *_end;
297
298 DEBUG (g_print ("---\n"));
299 DEBUG (pluma_text_region_debug_print (region));
300 DEBUG (g_message ("region_substract (%d, %d)",
301 gtk_text_iter_get_offset (&start),
302 gtk_text_iter_get_offset (&end)));
303
304 gtk_text_iter_order (&start, &end);
305
306 /* find bounding subregions */
307 start_node = find_nearest_subregion (region, &start, NULL((void*)0), FALSE(0), FALSE(0));
308 end_node = find_nearest_subregion (region, &end, start_node, TRUE(!(0)), FALSE(0));
309
310 /* easy case first */
311 if (start_node == NULL((void*)0) || end_node == NULL((void*)0) || end_node == start_node->prev)
312 return;
313
314 /* deal with the start point */
315 start_is_outside = end_is_outside = FALSE(0);
316
317 sr = start_node->data;
318 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start);
319 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end);
320
321 if (gtk_text_iter_in_range (&start, &sr_start_iter, &sr_end_iter) &&
322 !gtk_text_iter_equal (&start, &sr_start_iter)) {
323 /* the starting point is inside the first subregion */
324 if (gtk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter) &&
325 !gtk_text_iter_equal (&end, &sr_end_iter)) {
326 /* the ending point is also inside the first
327 subregion: we need to split */
328 Subregion *new_sr = g_new0 (Subregion, 1)(Subregion *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (Subregion); gpointer __p; if (__s == 1) __p = g_malloc0
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s); __p
; }))
;
329 new_sr->end = sr->end;
330 new_sr->start = gtk_text_buffer_create_mark (region->buffer,
331 NULL((void*)0), &end, TRUE(!(0)));
332 start_node = g_list_insert_before (start_node, start_node->next, new_sr);
333
334 sr->end = gtk_text_buffer_create_mark (region->buffer,
335 NULL((void*)0), &start, FALSE(0));
336
337 /* no further processing needed */
338 DEBUG (g_message ("subregion splitted"));
339
340 return;
341 } else {
342 /* the ending point is outside, so just move
343 the end of the subregion to the starting point */
344 gtk_text_buffer_move_mark (region->buffer, sr->end, &start);
345 }
346 } else {
347 /* the starting point is outside (and so to the left)
348 of the first subregion */
349 DEBUG (g_message ("start is outside"));
350
351 start_is_outside = TRUE(!(0));
352 }
353
354 /* deal with the end point */
355 if (start_node != end_node) {
356 sr = end_node->data;
357 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start);
358 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end);
359 }
360
361 if (gtk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter) &&
362 !gtk_text_iter_equal (&end, &sr_end_iter)) {
363 /* ending point is inside, move the start mark */
364 gtk_text_buffer_move_mark (region->buffer, sr->start, &end);
365 } else {
366 end_is_outside = TRUE(!(0));
367 DEBUG (g_message ("end is outside"));
368
369 }
370
371 /* finally remove any intermediate subregions */
372 done = FALSE(0);
373 node = start_node;
374
375 while (!done) {
376 if (node == end_node)
377 /* we are done, exit in the next iteration */
378 done = TRUE(!(0));
379
380 if ((node == start_node && !start_is_outside) ||
381 (node == end_node && !end_is_outside)) {
382 /* skip starting or ending node */
383 node = node->next;
384 } else {
385 GList *l = node->next;
386 sr = node->data;
387 gtk_text_buffer_delete_mark (region->buffer, sr->start);
388 gtk_text_buffer_delete_mark (region->buffer, sr->end);
389 g_free (sr);
390 region->subregions = g_list_delete_link (region->subregions,
391 node);
392 node = l;
393 }
394 }
395
396 ++region->time_stamp;
397
398 DEBUG (pluma_text_region_debug_print (region));
399
400 /* now get rid of empty subregions */
401 pluma_text_region_clear_zero_length_subregions (region);
402
403 DEBUG (pluma_text_region_debug_print (region));
404}
405
406gint
407pluma_text_region_subregions (PlumaTextRegion *region)
408{
409 g_return_val_if_fail (region != NULL, 0)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_38
; if (region != ((void*)0)) _g_boolean_var_38 = 1; else _g_boolean_var_38
= 0; _g_boolean_var_38; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return (0); } } while (0)
;
410
411 return g_list_length (region->subregions);
412}
413
414gboolean
415pluma_text_region_nth_subregion (PlumaTextRegion *region,
416 guint subregion,
417 GtkTextIter *start,
418 GtkTextIter *end)
419{
420 Subregion *sr;
421
422 g_return_val_if_fail (region != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_39
; if (region != ((void*)0)) _g_boolean_var_39 = 1; else _g_boolean_var_39
= 0; _g_boolean_var_39; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return ((0)); } } while (0)
;
423
424 sr = g_list_nth_data (region->subregions, subregion);
425 if (sr == NULL((void*)0))
426 return FALSE(0);
427
428 if (start)
429 gtk_text_buffer_get_iter_at_mark (region->buffer, start, sr->start);
430 if (end)
431 gtk_text_buffer_get_iter_at_mark (region->buffer, end, sr->end);
432
433 return TRUE(!(0));
434}
435
436PlumaTextRegion *
437pluma_text_region_intersect (PlumaTextRegion *region,
438 const GtkTextIter *_start,
439 const GtkTextIter *_end)
440{
441 GList *start_node, *end_node, *node;
442 GtkTextIter sr_start_iter, sr_end_iter;
443 Subregion *sr, *new_sr;
444 gboolean done;
445 PlumaTextRegion *new_region;
446 GtkTextIter start, end;
447
448 g_return_val_if_fail (region != NULL && _start != NULL && _end != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_40
; if (region != ((void*)0) && _start != ((void*)0) &&
_end != ((void*)0)) _g_boolean_var_40 = 1; else _g_boolean_var_40
= 0; _g_boolean_var_40; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL && _start != NULL && _end != NULL"
); return (((void*)0)); } } while (0)
;
449
450 start = *_start;
451 end = *_end;
452
453 gtk_text_iter_order (&start, &end);
454
455 /* find bounding subregions */
456 start_node = find_nearest_subregion (region, &start, NULL((void*)0), FALSE(0), FALSE(0));
457 end_node = find_nearest_subregion (region, &end, start_node, TRUE(!(0)), FALSE(0));
458
459 /* easy case first */
460 if (start_node == NULL((void*)0) || end_node == NULL((void*)0) || end_node == start_node->prev)
461 return NULL((void*)0);
462
463 new_region = pluma_text_region_new (region->buffer);
464 done = FALSE(0);
465
466 sr = start_node->data;
467 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start);
468 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end);
469
470 /* starting node */
471 if (gtk_text_iter_in_range (&start, &sr_start_iter, &sr_end_iter)) {
472 new_sr = g_new0 (Subregion, 1)(Subregion *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (Subregion); gpointer __p; if (__s == 1) __p = g_malloc0
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s); __p
; }))
;
473 new_region->subregions = g_list_prepend (new_region->subregions, new_sr);
474
475 new_sr->start = gtk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
476 &start, TRUE(!(0)));
477 if (start_node == end_node) {
478 /* things will finish shortly */
479 done = TRUE(!(0));
480 if (gtk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter))
481 new_sr->end = gtk_text_buffer_create_mark (new_region->buffer,
482 NULL((void*)0), &end, FALSE(0));
483 else
484 new_sr->end = gtk_text_buffer_create_mark (new_region->buffer,
485 NULL((void*)0), &sr_end_iter,
486 FALSE(0));
487 } else {
488 new_sr->end = gtk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
489 &sr_end_iter, FALSE(0));
490 }
491 node = start_node->next;
492 } else {
493 /* start should be the same as the subregion, so copy it in the loop */
494 node = start_node;
495 }
496
497 if (!done) {
498 while (node != end_node) {
499 /* copy intermediate subregions verbatim */
500 sr = node->data;
501 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter,
502 sr->start);
503 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end);
504
505 new_sr = g_new0 (Subregion, 1)(Subregion *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (Subregion); gpointer __p; if (__s == 1) __p = g_malloc0
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s); __p
; }))
;
506 new_region->subregions = g_list_prepend (new_region->subregions, new_sr);
507 new_sr->start = gtk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
508 &sr_start_iter, TRUE(!(0)));
509 new_sr->end = gtk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
510 &sr_end_iter, FALSE(0));
511 /* next node */
512 node = node->next;
513 }
514
515 /* ending node */
516 sr = node->data;
517 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_start_iter, sr->start);
518 gtk_text_buffer_get_iter_at_mark (region->buffer, &sr_end_iter, sr->end);
519
520 new_sr = g_new0 (Subregion, 1)(Subregion *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (Subregion); gpointer __p; if (__s == 1) __p = g_malloc0
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc0 (__n * __s); else __p = g_malloc0_n (__n, __s); __p
; }))
;
521 new_region->subregions = g_list_prepend (new_region->subregions, new_sr);
522
523 new_sr->start = gtk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
524 &sr_start_iter, TRUE(!(0)));
525
526 if (gtk_text_iter_in_range (&end, &sr_start_iter, &sr_end_iter))
527 new_sr->end = gtk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
528 &end, FALSE(0));
529 else
530 new_sr->end = gtk_text_buffer_create_mark (new_region->buffer, NULL((void*)0),
531 &sr_end_iter, FALSE(0));
532 }
533
534 new_region->subregions = g_list_reverse (new_region->subregions);
535 return new_region;
536}
537
538static gboolean
539check_iterator (PlumaTextRegionIteratorReal *real)
540{
541 if ((real->region == NULL((void*)0)) ||
542 (real->region_time_stamp != real->region->time_stamp))
543 {
544 g_warning("Invalid iterator: either the iterator "
545 "is uninitialized, or the region "
546 "has been modified since the iterator "
547 "was created.");
548
549 return FALSE(0);
550 }
551
552 return TRUE(!(0));
553}
554
555void
556pluma_text_region_get_iterator (PlumaTextRegion *region,
557 PlumaTextRegionIterator *iter,
558 guint start)
559{
560 PlumaTextRegionIteratorReal *real;
561
562 g_return_if_fail (region != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_41
; if (region != ((void*)0)) _g_boolean_var_41 = 1; else _g_boolean_var_41
= 0; _g_boolean_var_41; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return; } } while (0)
;
563 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_42
; if (iter != ((void*)0)) _g_boolean_var_42 = 1; else _g_boolean_var_42
= 0; _g_boolean_var_42; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
564
565 real = (PlumaTextRegionIteratorReal *)iter;
566
567 /* region->subregions may be NULL, -> end iter */
568
569 real->region = region;
570 real->subregions = g_list_nth (region->subregions, start);
571 real->region_time_stamp = region->time_stamp;
572}
573
574gboolean
575pluma_text_region_iterator_is_end (PlumaTextRegionIterator *iter)
576{
577 PlumaTextRegionIteratorReal *real;
578
579 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_43
; if (iter != ((void*)0)) _g_boolean_var_43 = 1; else _g_boolean_var_43
= 0; _g_boolean_var_43; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
580
581 real = (PlumaTextRegionIteratorReal *)iter;
582 g_return_val_if_fail (check_iterator (real), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_44
; if (check_iterator (real)) _g_boolean_var_44 = 1; else _g_boolean_var_44
= 0; _g_boolean_var_44; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "check_iterator (real)"
); return ((0)); } } while (0)
;
583
584 return (real->subregions == NULL((void*)0));
585}
586
587gboolean
588pluma_text_region_iterator_next (PlumaTextRegionIterator *iter)
589{
590 PlumaTextRegionIteratorReal *real;
591
592 g_return_val_if_fail (iter != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_45
; if (iter != ((void*)0)) _g_boolean_var_45 = 1; else _g_boolean_var_45
= 0; _g_boolean_var_45; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
((0)); } } while (0)
;
593
594 real = (PlumaTextRegionIteratorReal *)iter;
595 g_return_val_if_fail (check_iterator (real), FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_46
; if (check_iterator (real)) _g_boolean_var_46 = 1; else _g_boolean_var_46
= 0; _g_boolean_var_46; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "check_iterator (real)"
); return ((0)); } } while (0)
;
596
597 if (real->subregions != NULL((void*)0)) {
598 real->subregions = g_list_next (real->subregions)((real->subregions) ? (((GList *)(real->subregions))->
next) : ((void*)0))
;
599 return TRUE(!(0));
600 }
601 else
602 return FALSE(0);
603}
604
605void
606pluma_text_region_iterator_get_subregion (PlumaTextRegionIterator *iter,
607 GtkTextIter *start,
608 GtkTextIter *end)
609{
610 PlumaTextRegionIteratorReal *real;
611 Subregion *sr;
612
613 g_return_if_fail (iter != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_47
; if (iter != ((void*)0)) _g_boolean_var_47 = 1; else _g_boolean_var_47
= 0; _g_boolean_var_47; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "iter != NULL"); return
; } } while (0)
;
614
615 real = (PlumaTextRegionIteratorReal *)iter;
616 g_return_if_fail (check_iterator (real))do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_48
; if (check_iterator (real)) _g_boolean_var_48 = 1; else _g_boolean_var_48
= 0; _g_boolean_var_48; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "check_iterator (real)"
); return; } } while (0)
;
617 g_return_if_fail (real->subregions != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_49
; if (real->subregions != ((void*)0)) _g_boolean_var_49 = 1
; else _g_boolean_var_49 = 0; _g_boolean_var_49; }), 1))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "real->subregions != NULL"); return; } } while
(0)
;
618
619 sr = (Subregion*)real->subregions->data;
620 g_return_if_fail (sr != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_50
; if (sr != ((void*)0)) _g_boolean_var_50 = 1; else _g_boolean_var_50
= 0; _g_boolean_var_50; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "sr != NULL"); return
; } } while (0)
;
621
622 if (start)
623 gtk_text_buffer_get_iter_at_mark (real->region->buffer, start, sr->start);
624 if (end)
625 gtk_text_buffer_get_iter_at_mark (real->region->buffer, end, sr->end);
626}
627
628void
629pluma_text_region_debug_print (PlumaTextRegion *region)
630{
631 GList *l;
632
633 g_return_if_fail (region != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_51
; if (region != ((void*)0)) _g_boolean_var_51 = 1; else _g_boolean_var_51
= 0; _g_boolean_var_51; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "region != NULL")
; return; } } while (0)
;
634
635 g_print ("Subregions: ");
636 l = region->subregions;
637 while (l) {
638 Subregion *sr = l->data;
639 GtkTextIter iter1, iter2;
640 gtk_text_buffer_get_iter_at_mark (region->buffer, &iter1, sr->start);
641 gtk_text_buffer_get_iter_at_mark (region->buffer, &iter2, sr->end);
642 g_print ("%d-%d ", gtk_text_iter_get_offset (&iter1),
643 gtk_text_iter_get_offset (&iter2));
644 l = l->next;
645 }
646 g_print ("\n");
647}
diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-b8f564.html b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-b8f564.html new file mode 100644 index 00000000..b5b5f964 --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-b8f564.html @@ -0,0 +1,2089 @@ + + + +eggsmclient-xsmp.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:pluma/mate-submodules/libegg/eggsmclient-xsmp.c
Warning:line 1199, column 18
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name eggsmclient-xsmp.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/pluma/mate-submodules/libegg -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I ../../.. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -D EGG_SM_CLIENT_BACKEND_XSMP -D G_LOG_DOMAIN="EggSMClient" -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/pluma/mate-submodules/libegg -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-10-22-114445-13211-1 -x c eggsmclient-xsmp.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright (C) 2007 Novell, Inc.
3 *
4 * Inspired by various other pieces of code including GsmClient (C)
5 * 2001 Havoc Pennington, MateClient (C) 1998 Carsten Schaar, and twm
6 * session code (C) 1998 The Open Group.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24#include "config.h"
25
26#include "eggsmclient.h"
27#include "eggsmclient-private.h"
28
29#include "eggdesktopfile.h"
30
31#include <errno(*__errno_location ()).h>
32#include <fcntl.h>
33#include <stdlib.h>
34#include <string.h>
35#include <unistd.h>
36#include <X11/SM/SMlib.h>
37
38#include <gtk/gtk.h>
39#include <gdk/gdk.h>
40
41#if defined(GDK_WINDOWING_X11) || defined(HAVE_X11)
42#include <gdk/gdkx.h>
43#endif
44
45#define EGG_TYPE_SM_CLIENT_XSMP(egg_sm_client_xsmp_get_type ()) (egg_sm_client_xsmp_get_type ())
46#define EGG_SM_CLIENT_XSMP(obj)((((EggSMClientXSMP*) (void *) ((obj))))) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT_XSMP, EggSMClientXSMP)(((EggSMClientXSMP*) (void *) ((obj)))))
47#define EGG_SM_CLIENT_XSMP_CLASS(klass)((((EggSMClientXSMPClass*) (void *) ((klass))))) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT_XSMP, EggSMClientXSMPClass)(((EggSMClientXSMPClass*) (void *) ((klass)))))
48#define EGG_IS_SM_CLIENT_XSMP(obj)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(obj)); GType __t = ((egg_sm_client_xsmp_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT_XSMP)((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(obj)); GType __t = ((egg_sm_client_xsmp_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))
)
49#define EGG_IS_SM_CLIENT_XSMP_CLASS(klass)(((__extension__ ({ GTypeClass *__class = (GTypeClass*) ((klass
)); GType __t = ((egg_sm_client_xsmp_get_type ())); gboolean __r
; if (!__class) __r = (0); else if (__class->g_type == __t
) __r = (!(0)); else __r = g_type_check_class_is_a (__class, __t
); __r; }))))
(G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT_XSMP)((__extension__ ({ GTypeClass *__class = (GTypeClass*) ((klass
)); GType __t = ((egg_sm_client_xsmp_get_type ())); gboolean __r
; if (!__class) __r = (0); else if (__class->g_type == __t
) __r = (!(0)); else __r = g_type_check_class_is_a (__class, __t
); __r; })))
)
50#define EGG_SM_CLIENT_XSMP_GET_CLASS(obj)((((EggSMClientXSMPClass*) (((GTypeInstance*) ((obj)))->g_class
))))
(G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT_XSMP, EggSMClientXSMPClass)(((EggSMClientXSMPClass*) (((GTypeInstance*) ((obj)))->g_class
)))
)
51
52typedef struct _EggSMClientXSMP EggSMClientXSMP;
53typedef struct _EggSMClientXSMPClass EggSMClientXSMPClass;
54
55/* These mostly correspond to the similarly-named states in section
56 * 9.1 of the XSMP spec. Some of the states there aren't represented
57 * here, because we don't need them. SHUTDOWN_CANCELLED is slightly
58 * different from the spec; we use it when the client is IDLE after a
59 * ShutdownCancelled message, but the application is still interacting
60 * and doesn't know the shutdown has been cancelled yet.
61 */
62typedef enum
63{
64 XSMP_STATE_IDLE,
65 XSMP_STATE_SAVE_YOURSELF,
66 XSMP_STATE_INTERACT_REQUEST,
67 XSMP_STATE_INTERACT,
68 XSMP_STATE_SAVE_YOURSELF_DONE,
69 XSMP_STATE_SHUTDOWN_CANCELLED,
70 XSMP_STATE_CONNECTION_CLOSED
71} EggSMClientXSMPState;
72
73static const char *state_names[] =
74{
75 "idle",
76 "save-yourself",
77 "interact-request",
78 "interact",
79 "save-yourself-done",
80 "shutdown-cancelled",
81 "connection-closed"
82};
83
84#define EGG_SM_CLIENT_XSMP_STATE(xsmp)(state_names[(xsmp)->state]) (state_names[(xsmp)->state])
85
86struct _EggSMClientXSMP
87{
88 EggSMClient parent;
89
90 SmcConn connection;
91 char *client_id;
92
93 EggSMClientXSMPState state;
94 char **restart_command;
95 gboolean set_restart_command;
96 int restart_style;
97 char **discard_command;
98 gboolean set_discard_command;
99
100 guint idle;
101
102 /* Current SaveYourself state */
103 guint expecting_initial_save_yourself : 1;
104 guint need_save_state : 1;
105 guint need_quit_requested : 1;
106 guint interact_errors : 1;
107 guint shutting_down : 1;
108
109 /* Todo list */
110 guint waiting_to_set_initial_properties : 1;
111 guint waiting_to_emit_quit : 1;
112 guint waiting_to_emit_quit_cancelled : 1;
113 guint waiting_to_save_myself : 1;
114
115};
116
117struct _EggSMClientXSMPClass
118{
119 EggSMClientClass parent_class;
120
121};
122
123static void sm_client_xsmp_startup (EggSMClient *client,
124 const char *client_id);
125static void sm_client_xsmp_set_restart_command (EggSMClient *client,
126 int argc,
127 const char **argv);
128static void sm_client_xsmp_set_discard_command (EggSMClient *client,
129 int argc,
130 const char **argv);
131static void sm_client_xsmp_will_quit (EggSMClient *client,
132 gboolean will_quit);
133static gboolean sm_client_xsmp_end_session (EggSMClient *client,
134 EggSMClientEndStyle style,
135 gboolean request_confirmation);
136
137static void xsmp_save_yourself (SmcConn smc_conn,
138 SmPointer client_data,
139 int save_style,
140 Boolint shutdown,
141 int interact_style,
142 Boolint fast);
143static void xsmp_die (SmcConn smc_conn,
144 SmPointer client_data);
145static void xsmp_save_complete (SmcConn smc_conn,
146 SmPointer client_data);
147static void xsmp_shutdown_cancelled (SmcConn smc_conn,
148 SmPointer client_data);
149static void xsmp_interact (SmcConn smc_conn,
150 SmPointer client_data);
151
152static SmProp *array_prop (const char *name,
153 ...);
154static SmProp *ptrarray_prop (const char *name,
155 GPtrArray *values);
156static SmProp *string_prop (const char *name,
157 const char *value);
158static SmProp *card8_prop (const char *name,
159 unsigned char value);
160
161static void set_properties (EggSMClientXSMP *xsmp, ...);
162static void delete_properties (EggSMClientXSMP *xsmp, ...);
163
164static GPtrArray *generate_command (char **restart_command,
165 const char *client_id,
166 const char *state_file);
167
168static void save_state (EggSMClientXSMP *xsmp);
169static void do_save_yourself (EggSMClientXSMP *xsmp);
170static void update_pending_events (EggSMClientXSMP *xsmp);
171
172static void ice_init (void);
173static gboolean process_ice_messages (IceConn ice_conn);
174static void smc_error_handler (SmcConn smc_conn,
175 Boolint swap,
176 int offending_minor_opcode,
177 unsigned long offending_sequence,
178 int error_class,
179 int severity,
180 SmPointer values);
181
182G_DEFINE_TYPE (EggSMClientXSMP, egg_sm_client_xsmp, EGG_TYPE_SM_CLIENT)static void egg_sm_client_xsmp_init (EggSMClientXSMP *self); static
void egg_sm_client_xsmp_class_init (EggSMClientXSMPClass *klass
); static GType egg_sm_client_xsmp_get_type_once (void); static
gpointer egg_sm_client_xsmp_parent_class = ((void*)0); static
gint EggSMClientXSMP_private_offset; static void egg_sm_client_xsmp_class_intern_init
(gpointer klass) { egg_sm_client_xsmp_parent_class = g_type_class_peek_parent
(klass); if (EggSMClientXSMP_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EggSMClientXSMP_private_offset); egg_sm_client_xsmp_class_init
((EggSMClientXSMPClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer egg_sm_client_xsmp_get_instance_private
(EggSMClientXSMP *self) { return (((gpointer) ((guint8*) (self
) + (glong) (EggSMClientXSMP_private_offset)))); } GType egg_sm_client_xsmp_get_type
(void) { static gsize static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) *(&static_g_define_type_id) : ((void*)0));
(!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id
)); }))) { GType g_define_type_id = egg_sm_client_xsmp_get_type_once
(); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&static_g_define_type_id) = (g_define_type_id)
) : (void) 0; g_once_init_leave ((&static_g_define_type_id
), (gsize) (g_define_type_id)); })); } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType egg_sm_client_xsmp_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((egg_sm_client_get_type ()), g_intern_static_string ("EggSMClientXSMP"
), sizeof (EggSMClientXSMPClass), (GClassInitFunc)(void (*)(void
)) egg_sm_client_xsmp_class_intern_init, sizeof (EggSMClientXSMP
), (GInstanceInitFunc)(void (*)(void)) egg_sm_client_xsmp_init
, (GTypeFlags) 0); { {{};} } return g_define_type_id; }
183
184static void
185egg_sm_client_xsmp_init (EggSMClientXSMP *xsmp)
186{
187 xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
188 xsmp->connection = NULL((void*)0);
189 xsmp->restart_style = SmRestartIfRunning0;
190}
191
192static void
193egg_sm_client_xsmp_class_init (EggSMClientXSMPClass *klass)
194{
195 EggSMClientClass *sm_client_class = EGG_SM_CLIENT_CLASS (klass);
196
197 sm_client_class->startup = sm_client_xsmp_startup;
198 sm_client_class->set_restart_command = sm_client_xsmp_set_restart_command;
199 sm_client_class->set_discard_command = sm_client_xsmp_set_discard_command;
200 sm_client_class->will_quit = sm_client_xsmp_will_quit;
201 sm_client_class->end_session = sm_client_xsmp_end_session;
202}
203
204EggSMClient *
205egg_sm_client_xsmp_new (void)
206{
207 if (!g_getenv ("SESSION_MANAGER"))
208 return NULL((void*)0);
209
210 return g_object_new (EGG_TYPE_SM_CLIENT_XSMP(egg_sm_client_xsmp_get_type ()), NULL((void*)0));
211}
212
213static gboolean
214sm_client_xsmp_set_initial_properties (gpointer user_data)
215{
216 EggSMClientXSMP *xsmp = user_data;
217 EggDesktopFile *desktop_file;
218 GPtrArray *clone, *restart;
219 char pid_str[64];
220
221 if (xsmp->idle)
222 {
223 g_source_remove (xsmp->idle);
224 xsmp->idle = 0;
225 }
226 xsmp->waiting_to_set_initial_properties = FALSE(0);
227
228 if (egg_sm_client_get_mode () == EGG_SM_CLIENT_MODE_NO_RESTART)
229 xsmp->restart_style = SmRestartNever3;
230
231 /* Parse info out of desktop file */
232 desktop_file = egg_get_desktop_file ();
233 if (desktop_file)
234 {
235 GError *err = NULL((void*)0);
236 char **argv;
237 int argc;
238
239 if (xsmp->restart_style == SmRestartIfRunning0)
240 {
241 if (egg_desktop_file_get_boolean (desktop_file,
242 "X-MATE-AutoRestart", NULL((void*)0)))
243 xsmp->restart_style = SmRestartImmediately2;
244 }
245
246 if (!xsmp->set_restart_command)
247 {
248 char *cmdline;
249
250 cmdline = egg_desktop_file_parse_exec (desktop_file, NULL((void*)0), &err);
251 if (cmdline && g_shell_parse_argv (cmdline, &argc, &argv, &err))
252 {
253 egg_sm_client_set_restart_command (EGG_SM_CLIENT (xsmp),
254 argc, (const char **)argv);
255 g_strfreev (argv);
256 }
257 else
258 {
259 g_warning ("Could not parse Exec line in desktop file: %s",
260 err->message);
261 g_error_free (err);
262 }
263 g_free (cmdline);
264 }
265 }
266
267 if (!xsmp->set_restart_command)
268 xsmp->restart_command = g_strsplit (g_get_prgname (), " ", -1);
269
270 clone = generate_command (xsmp->restart_command, NULL((void*)0), NULL((void*)0));
271 restart = generate_command (xsmp->restart_command, xsmp->client_id, NULL((void*)0));
272
273 g_debug ("Setting initial properties");
274
275 /* Program, CloneCommand, RestartCommand, and UserID are required.
276 * ProcessID isn't required, but the SM may be able to do something
277 * useful with it.
278 */
279 g_snprintf (pid_str, sizeof (pid_str), "%lu", (gulong) getpid ());
280 set_properties (xsmp,
281 string_prop (SmProgram"Program", g_get_prgname ()),
282 ptrarray_prop (SmCloneCommand"CloneCommand", clone),
283 ptrarray_prop (SmRestartCommand"RestartCommand", restart),
284 string_prop (SmUserID"UserID", g_get_user_name ()),
285 string_prop (SmProcessID"ProcessID", pid_str),
286 card8_prop (SmRestartStyleHint"RestartStyleHint", xsmp->restart_style),
287 NULL((void*)0));
288 g_ptr_array_free (clone, TRUE(!(0)));
289 g_ptr_array_free (restart, TRUE(!(0)));
290
291 if (desktop_file)
292 {
293 set_properties (xsmp,
294 string_prop ("_GSM_DesktopFile", egg_desktop_file_get_source (desktop_file)),
295 NULL((void*)0));
296 }
297
298 update_pending_events (xsmp);
299 return FALSE(0);
300}
301
302/* This gets called from two different places: xsmp_die() (when the
303 * server asks us to disconnect) and process_ice_messages() (when the
304 * server disconnects unexpectedly).
305 */
306static void
307sm_client_xsmp_disconnect (EggSMClientXSMP *xsmp)
308{
309 SmcConn connection;
310
311 if (!xsmp->connection)
312 return;
313
314 g_debug ("Disconnecting");
315
316 connection = xsmp->connection;
317 xsmp->connection = NULL((void*)0);
318 SmcCloseConnection (connection, 0, NULL((void*)0));
319 xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
320
321 xsmp->waiting_to_save_myself = FALSE(0);
322 update_pending_events (xsmp);
323}
324
325static void
326sm_client_xsmp_startup (EggSMClient *client,
327 const char *client_id)
328{
329 EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
330 SmcCallbacks callbacks;
331 char *ret_client_id;
332 char error_string_ret[256];
333
334 xsmp->client_id = g_strdup (client_id)g_strdup_inline (client_id);
335
336 ice_init ();
337 SmcSetErrorHandler (smc_error_handler);
338
339 callbacks.save_yourself.callback = xsmp_save_yourself;
340 callbacks.die.callback = xsmp_die;
341 callbacks.save_complete.callback = xsmp_save_complete;
342 callbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
343
344 callbacks.save_yourself.client_data = xsmp;
345 callbacks.die.client_data = xsmp;
346 callbacks.save_complete.client_data = xsmp;
347 callbacks.shutdown_cancelled.client_data = xsmp;
348
349 client_id = NULL((void*)0);
350 error_string_ret[0] = '\0';
351 xsmp->connection =
352 SmcOpenConnection (NULL((void*)0), xsmp, SmProtoMajor1, SmProtoMinor0,
353 SmcSaveYourselfProcMask(1L << 0) | SmcDieProcMask(1L << 1) |
354 SmcSaveCompleteProcMask(1L << 2) |
355 SmcShutdownCancelledProcMask(1L << 3),
356 &callbacks,
357 xsmp->client_id, &ret_client_id,
358 sizeof (error_string_ret), error_string_ret);
359
360 if (!xsmp->connection)
361 {
362 g_warning ("Failed to connect to the session manager: %s\n",
363 error_string_ret[0] ?
364 error_string_ret : "no error message given");
365 xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
366 return;
367 }
368
369 /* We expect a pointless initial SaveYourself if either (a) we
370 * didn't have an initial client ID, or (b) we DID have an initial
371 * client ID, but the server rejected it and gave us a new one.
372 */
373 if (!xsmp->client_id ||
374 (ret_client_id && strcmp (xsmp->client_id, ret_client_id) != 0))
375 xsmp->expecting_initial_save_yourself = TRUE(!(0));
376
377 if (ret_client_id)
378 {
379 g_free (xsmp->client_id);
380 xsmp->client_id = g_strdup (ret_client_id)g_strdup_inline (ret_client_id);
381 free (ret_client_id);
382
383#if defined(GDK_WINDOWING_X11) || defined(HAVE_X11)
384 if (GDK_IS_X11_DISPLAY (gdk_display_get_default ())(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(gdk_display_get_default ())); GType __t = ((gdk_x11_display_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
385 gdk_x11_set_sm_client_id (xsmp->client_id);
386#endif
387
388 g_debug ("Got client ID \"%s\"", xsmp->client_id);
389 }
390
391 xsmp->state = XSMP_STATE_IDLE;
392
393 /* Do not set the initial properties until we reach the main loop,
394 * so that the application has a chance to call
395 * egg_set_desktop_file(). (This may also help the session manager
396 * have a better idea of when the application is fully up and
397 * running.)
398 */
399 xsmp->waiting_to_set_initial_properties = TRUE(!(0));
400 xsmp->idle = g_idle_add (sm_client_xsmp_set_initial_properties, client);
401}
402
403static void
404sm_client_xsmp_set_restart_command (EggSMClient *client,
405 int argc,
406 const char **argv)
407{
408 EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
409 int i;
410
411 g_strfreev (xsmp->restart_command);
412
413 xsmp->restart_command = g_new (char *, argc + 1)(char * *) (__extension__ ({ gsize __n = (gsize) (argc + 1); gsize
__s = sizeof (char *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
414 for (i = 0; i < argc; i++)
415 xsmp->restart_command[i] = g_strdup (argv[i])g_strdup_inline (argv[i]);
416 xsmp->restart_command[i] = NULL((void*)0);
417
418 xsmp->set_restart_command = TRUE(!(0));
419}
420
421static void
422sm_client_xsmp_set_discard_command (EggSMClient *client,
423 int argc,
424 const char **argv)
425{
426 EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
427 int i;
428
429 g_strfreev (xsmp->discard_command);
430
431 xsmp->discard_command = g_new (char *, argc + 1)(char * *) (__extension__ ({ gsize __n = (gsize) (argc + 1); gsize
__s = sizeof (char *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
432 for (i = 0; i < argc; i++)
433 xsmp->discard_command[i] = g_strdup (argv[i])g_strdup_inline (argv[i]);
434 xsmp->discard_command[i] = NULL((void*)0);
435
436 xsmp->set_discard_command = TRUE(!(0));
437}
438
439static void
440sm_client_xsmp_will_quit (EggSMClient *client,
441 gboolean will_quit)
442{
443 EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
444
445 if (xsmp->state == XSMP_STATE_CONNECTION_CLOSED)
446 {
447 /* The session manager has already exited! Schedule a quit
448 * signal.
449 */
450 xsmp->waiting_to_emit_quit = TRUE(!(0));
451 update_pending_events (xsmp);
452 return;
453 }
454 else if (xsmp->state == XSMP_STATE_SHUTDOWN_CANCELLED)
455 {
456 /* We received a ShutdownCancelled message while the application
457 * was interacting; Schedule a quit_cancelled signal.
458 */
459 xsmp->waiting_to_emit_quit_cancelled = TRUE(!(0));
460 update_pending_events (xsmp);
461 return;
462 }
463
464 g_return_if_fail (xsmp->state == XSMP_STATE_INTERACT)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_11
; if (xsmp->state == XSMP_STATE_INTERACT) _g_boolean_var_11
= 1; else _g_boolean_var_11 = 0; _g_boolean_var_11; }), 1)))
{ } else { g_return_if_fail_warning ("EggSMClient", ((const char
*) (__func__)), "xsmp->state == XSMP_STATE_INTERACT"); return
; } } while (0)
;
465
466 g_debug ("Sending InteractDone(%s)", will_quit ? "False" : "True");
467 SmcInteractDone (xsmp->connection, !will_quit);
468
469 if (will_quit && xsmp->need_save_state)
470 save_state (xsmp);
471
472 g_debug ("Sending SaveYourselfDone(%s)", will_quit ? "True" : "False");
473 SmcSaveYourselfDone (xsmp->connection, will_quit);
474 xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
475}
476
477static gboolean
478sm_client_xsmp_end_session (EggSMClient *client,
479 EggSMClientEndStyle style,
480 gboolean request_confirmation)
481{
482 EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
483 int save_type;
484
485 /* To end the session via XSMP, we have to send a
486 * SaveYourselfRequest. We aren't allowed to do that if anything
487 * else is going on, but we don't want to expose this fact to the
488 * application. So we do our best to patch things up here...
489 *
490 * In the worst case, this method might block for some length of
491 * time in process_ice_messages, but the only time that code path is
492 * honestly likely to get hit is if the application tries to end the
493 * session as the very first thing it does, in which case it
494 * probably won't actually block anyway. It's not worth gunking up
495 * the API to try to deal nicely with the other 0.01% of cases where
496 * this happens.
497 */
498
499 while (xsmp->state != XSMP_STATE_IDLE ||
500 xsmp->expecting_initial_save_yourself)
501 {
502 /* If we're already shutting down, we don't need to do anything. */
503 if (xsmp->shutting_down)
504 return TRUE(!(0));
505
506 switch (xsmp->state)
507 {
508 case XSMP_STATE_CONNECTION_CLOSED:
509 return FALSE(0);
510
511 case XSMP_STATE_SAVE_YOURSELF:
512 /* Trying to log out from the save_state callback? Whatever.
513 * Abort the save_state.
514 */
515 SmcSaveYourselfDone (xsmp->connection, FALSE(0));
516 xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
517 break;
518
519 case XSMP_STATE_INTERACT_REQUEST:
520 case XSMP_STATE_INTERACT:
521 case XSMP_STATE_SHUTDOWN_CANCELLED:
522 /* Already in a shutdown-related state, just ignore
523 * the new shutdown request...
524 */
525 return TRUE(!(0));
526
527 case XSMP_STATE_IDLE:
528 if (xsmp->waiting_to_set_initial_properties)
529 sm_client_xsmp_set_initial_properties (xsmp);
530
531 if (!xsmp->expecting_initial_save_yourself)
532 break;
533 /* else fall through */
534
535 case XSMP_STATE_SAVE_YOURSELF_DONE:
536 /* We need to wait for some response from the server.*/
537 process_ice_messages (SmcGetIceConnection (xsmp->connection));
538 break;
539
540 default:
541 /* Hm... shouldn't happen */
542 return FALSE(0);
543 }
544 }
545
546 /* xfce4-session will do the wrong thing if we pass SmSaveGlobal and
547 * the user chooses to save the session. But mate-session will do
548 * the wrong thing if we pass SmSaveBoth and the user chooses NOT to
549 * save the session... Sigh.
550 */
551 if (!strcmp (SmcVendor (xsmp->connection), "xfce4-session"))
552 save_type = SmSaveBoth2;
553 else
554 save_type = SmSaveGlobal0;
555
556 g_debug ("Sending SaveYourselfRequest(SmSaveGlobal, Shutdown, SmInteractStyleAny, %sFast)", request_confirmation ? "!" : "");
557 SmcRequestSaveYourself (xsmp->connection,
558 save_type,
559 True1, /* shutdown */
560 SmInteractStyleAny2,
561 !request_confirmation, /* fast */
562 True1 /* global */);
563 return TRUE(!(0));
564}
565
566static gboolean
567idle_do_pending_events (gpointer data)
568{
569 EggSMClientXSMP *xsmp = data;
570 EggSMClient *client = data;
571
572 xsmp->idle = 0;
573
574 if (xsmp->waiting_to_emit_quit)
575 {
576 xsmp->waiting_to_emit_quit = FALSE(0);
577 egg_sm_client_quit (client);
578 goto out;
579 }
580
581 if (xsmp->waiting_to_emit_quit_cancelled)
582 {
583 xsmp->waiting_to_emit_quit_cancelled = FALSE(0);
584 egg_sm_client_quit_cancelled (client);
585 xsmp->state = XSMP_STATE_IDLE;
586 }
587
588 if (xsmp->waiting_to_save_myself)
589 {
590 xsmp->waiting_to_save_myself = FALSE(0);
591 do_save_yourself (xsmp);
592 }
593
594out:
595 return FALSE(0);
596}
597
598static void
599update_pending_events (EggSMClientXSMP *xsmp)
600{
601 gboolean want_idle =
602 xsmp->waiting_to_emit_quit ||
603 xsmp->waiting_to_emit_quit_cancelled ||
604 xsmp->waiting_to_save_myself;
605
606 if (want_idle)
607 {
608 if (xsmp->idle == 0)
609 xsmp->idle = g_idle_add (idle_do_pending_events, xsmp);
610 }
611 else
612 {
613 if (xsmp->idle != 0)
614 g_source_remove (xsmp->idle);
615 xsmp->idle = 0;
616 }
617}
618
619static void
620fix_broken_state (EggSMClientXSMP *xsmp, const char *message,
621 gboolean send_interact_done,
622 gboolean send_save_yourself_done)
623{
624 g_warning ("Received XSMP %s message in state %s: client or server error",
625 message, EGG_SM_CLIENT_XSMP_STATE (xsmp)(state_names[(xsmp)->state]));
626
627 /* Forget any pending SaveYourself plans we had */
628 xsmp->waiting_to_save_myself = FALSE(0);
629 update_pending_events (xsmp);
630
631 if (send_interact_done)
632 SmcInteractDone (xsmp->connection, False0);
633 if (send_save_yourself_done)
634 SmcSaveYourselfDone (xsmp->connection, True1);
635
636 xsmp->state = send_save_yourself_done ? XSMP_STATE_SAVE_YOURSELF_DONE : XSMP_STATE_IDLE;
637}
638
639/* SM callbacks */
640
641static void
642xsmp_save_yourself (SmcConn smc_conn,
643 SmPointer client_data,
644 int save_type,
645 Boolint shutdown,
646 int interact_style,
647 Boolint fast)
648{
649 EggSMClientXSMP *xsmp = client_data;
650 gboolean wants_quit_requested;
651
652 g_debug ("Received SaveYourself(%s, %s, %s, %s) in state %s",
653 save_type == SmSaveLocal1 ? "SmSaveLocal" :
654 save_type == SmSaveGlobal0 ? "SmSaveGlobal" : "SmSaveBoth",
655 shutdown ? "Shutdown" : "!Shutdown",
656 interact_style == SmInteractStyleAny2 ? "SmInteractStyleAny" :
657 interact_style == SmInteractStyleErrors1 ? "SmInteractStyleErrors" :
658 "SmInteractStyleNone", fast ? "Fast" : "!Fast",
659 EGG_SM_CLIENT_XSMP_STATE (xsmp)(state_names[(xsmp)->state]));
660
661 if (xsmp->state != XSMP_STATE_IDLE &&
662 xsmp->state != XSMP_STATE_SHUTDOWN_CANCELLED)
663 {
664 fix_broken_state (xsmp, "SaveYourself", FALSE(0), TRUE(!(0)));
665 return;
666 }
667
668 if (xsmp->waiting_to_set_initial_properties)
669 sm_client_xsmp_set_initial_properties (xsmp);
670
671 /* If this is the initial SaveYourself, ignore it; we've already set
672 * properties and there's no reason to actually save state too.
673 */
674 if (xsmp->expecting_initial_save_yourself)
675 {
676 xsmp->expecting_initial_save_yourself = FALSE(0);
677
678 if (save_type == SmSaveLocal1 &&
679 interact_style == SmInteractStyleNone0 &&
680 !shutdown && !fast)
681 {
682 g_debug ("Sending SaveYourselfDone(True) for initial SaveYourself");
683 SmcSaveYourselfDone (xsmp->connection, True1);
684 /* As explained in the comment at the end of
685 * do_save_yourself(), SAVE_YOURSELF_DONE is the correct
686 * state here, not IDLE.
687 */
688 xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
689 return;
690 }
691 else
692 g_warning ("First SaveYourself was not the expected one!");
693 }
694
695 /* Even ignoring the "fast" flag completely, there are still 18
696 * different combinations of save_type, shutdown and interact_style.
697 * We interpret them as follows:
698 *
699 * Type Shutdown Interact Interpretation
700 * G F A/E/N do nothing (1)
701 * G T N do nothing (1)*
702 * G T A/E quit_requested (2)
703 * L/B F A/E/N save_state (3)
704 * L/B T N save_state (3)*
705 * L/B T A/E quit_requested, then save_state (4)
706 *
707 * 1. Do nothing, because the SM asked us to do something
708 * uninteresting (save open files, but then don't quit
709 * afterward) or rude (save open files without asking the user
710 * for confirmation).
711 *
712 * 2. Request interaction and then emit ::quit_requested. This
713 * perhaps isn't quite correct for the SmInteractStyleErrors
714 * case, but we don't care.
715 *
716 * 3. Emit ::save_state. The SmSaveBoth SaveYourselfs in these
717 * rows essentially get demoted to SmSaveLocal, because their
718 * Global halves correspond to "do nothing".
719 *
720 * 4. Request interaction, emit ::quit_requested, and then emit
721 * ::save_state after interacting. This is the SmSaveBoth
722 * equivalent of #2, but we also promote SmSaveLocal shutdown
723 * SaveYourselfs to SmSaveBoth here, because we want to give
724 * the user a chance to save open files before quitting.
725 *
726 * (* It would be nice if we could do something useful when the
727 * session manager sends a SaveYourself with shutdown True and
728 * SmInteractStyleNone. But we can't, so we just pretend it didn't
729 * even tell us it was shutting down. The docs for ::quit mention
730 * that it might not always be preceded by ::quit_requested.)
731 */
732
733 /* As an optimization, we don't actually request interaction and
734 * emit ::quit_requested if the application isn't listening to the
735 * signal.
736 */
737 wants_quit_requested = g_signal_has_handler_pending (xsmp, g_signal_lookup ("quit_requested", EGG_TYPE_SM_CLIENT(egg_sm_client_get_type ())), 0, FALSE(0));
738
739 xsmp->need_save_state = (save_type != SmSaveGlobal0);
740 xsmp->need_quit_requested = (shutdown && wants_quit_requested &&
741 interact_style != SmInteractStyleNone0);
742 xsmp->interact_errors = (interact_style == SmInteractStyleErrors1);
743
744 xsmp->shutting_down = shutdown;
745
746 do_save_yourself (xsmp);
747}
748
749static void
750do_save_yourself (EggSMClientXSMP *xsmp)
751{
752 if (xsmp->state == XSMP_STATE_SHUTDOWN_CANCELLED)
753 {
754 /* The SM cancelled a previous SaveYourself, but we haven't yet
755 * had a chance to tell the application, so we can't start
756 * processing this SaveYourself yet.
757 */
758 xsmp->waiting_to_save_myself = TRUE(!(0));
759 update_pending_events (xsmp);
760 return;
761 }
762
763 if (xsmp->need_quit_requested)
764 {
765 xsmp->state = XSMP_STATE_INTERACT_REQUEST;
766
767 g_debug ("Sending InteractRequest(%s)",
768 xsmp->interact_errors ? "Error" : "Normal");
769 SmcInteractRequest (xsmp->connection,
770 xsmp->interact_errors ? SmDialogError0 : SmDialogNormal1,
771 xsmp_interact,
772 xsmp);
773 return;
774 }
775
776 if (xsmp->need_save_state)
777 {
778 save_state (xsmp);
779
780 /* Though unlikely, the client could have been disconnected
781 * while the application was saving its state.
782 */
783 if (!xsmp->connection)
784 return;
785 }
786
787 g_debug ("Sending SaveYourselfDone(True)");
788 SmcSaveYourselfDone (xsmp->connection, True1);
789
790 /* The client state diagram in the XSMP spec says that after a
791 * non-shutdown SaveYourself, we go directly back to "idle". But
792 * everything else in both the XSMP spec and the libSM docs
793 * disagrees.
794 */
795 xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
796}
797
798static void
799save_state (EggSMClientXSMP *xsmp)
800{
801 GKeyFile *state_file;
802 char *state_file_path, *data;
803 EggDesktopFile *desktop_file;
804 GPtrArray *restart, *discard;
805 int offset, fd;
806
807 /* We set xsmp->state before emitting save_state, but our caller is
808 * responsible for setting it back afterward.
809 */
810 xsmp->state = XSMP_STATE_SAVE_YOURSELF;
811
812 state_file = egg_sm_client_save_state ((EggSMClient *)xsmp);
813 if (!state_file)
814 {
815 restart = generate_command (xsmp->restart_command, xsmp->client_id, NULL((void*)0));
816 set_properties (xsmp,
817 ptrarray_prop (SmRestartCommand"RestartCommand", restart),
818 NULL((void*)0));
819 g_ptr_array_free (restart, TRUE(!(0)));
820
821 if (xsmp->set_discard_command)
822 {
823 discard = generate_command (xsmp->discard_command, NULL((void*)0), NULL((void*)0));
824 set_properties (xsmp,
825 ptrarray_prop (SmDiscardCommand"DiscardCommand", discard),
826 NULL((void*)0));
827 g_ptr_array_free (discard, TRUE(!(0)));
828 }
829 else
830 delete_properties (xsmp, SmDiscardCommand"DiscardCommand", NULL((void*)0));
831
832 return;
833 }
834
835 desktop_file = egg_get_desktop_file ();
836 if (desktop_file)
837 {
838 GKeyFile *merged_file;
839 char *desktop_file_path;
840
841 merged_file = g_key_file_new ();
842 desktop_file_path =
843 g_filename_from_uri (egg_desktop_file_get_source (desktop_file),
844 NULL((void*)0), NULL((void*)0));
845 if (desktop_file_path &&
846 g_key_file_load_from_file (merged_file, desktop_file_path,
847 G_KEY_FILE_KEEP_COMMENTS |
848 G_KEY_FILE_KEEP_TRANSLATIONS, NULL((void*)0)))
849 {
850 guint g, k, i;
851 char **groups, **keys, *value, *exec;
852
853 groups = g_key_file_get_groups (state_file, NULL((void*)0));
854 for (g = 0; groups[g]; g++)
855 {
856 keys = g_key_file_get_keys (state_file, groups[g], NULL((void*)0), NULL((void*)0));
857 for (k = 0; keys[k]; k++)
858 {
859 value = g_key_file_get_value (state_file, groups[g],
860 keys[k], NULL((void*)0));
861 if (value)
862 {
863 g_key_file_set_value (merged_file, groups[g],
864 keys[k], value);
865 g_free (value);
866 }
867 }
868 g_strfreev (keys);
869 }
870 g_strfreev (groups);
871
872 g_key_file_free (state_file);
873 state_file = merged_file;
874
875 /* Update Exec key using "--sm-client-state-file %k" */
876 restart = generate_command (xsmp->restart_command,
877 NULL((void*)0), "%k");
878 for (i = 0; i < restart->len; i++)
879 restart->pdata[i] = g_shell_quote (restart->pdata[i]);
880 g_ptr_array_add (restart, NULL((void*)0));
881 exec = g_strjoinv (" ", (char **)restart->pdata);
882 g_strfreev ((char **)restart->pdata);
883 g_ptr_array_free (restart, FALSE(0));
884
885 g_key_file_set_string (state_file, EGG_DESKTOP_FILE_GROUP"Desktop Entry",
886 EGG_DESKTOP_FILE_KEY_EXEC"Exec",
887 exec);
888 g_free (exec);
889 }
890 else
891 desktop_file = NULL((void*)0);
892
893 g_free (desktop_file_path);
894 }
895
896 /* Now write state_file to disk. (We can't use mktemp(), because
897 * that requires the filename to end with "XXXXXX", and we want
898 * it to end with ".desktop".)
899 */
900
901 data = g_key_file_to_data (state_file, NULL((void*)0), NULL((void*)0));
902 g_key_file_free (state_file);
903
904 offset = 0;
905 while (1)
906 {
907 state_file_path = g_strdup_printf ("%s%csession-state%c%s-%ld.%s",
908 g_get_user_config_dir (),
909 G_DIR_SEPARATOR'/', G_DIR_SEPARATOR'/',
910 g_get_prgname (),
911 (long)time (NULL((void*)0)) + offset,
912 desktop_file ? "desktop" : "state");
913
914 fd = open (state_file_path, O_WRONLY01 | O_CREAT0100 | O_EXCL0200, 0644);
915 if (fd == -1)
916 {
917 if (errno(*__errno_location ()) == EEXIST17)
918 {
919 offset++;
920 g_free (state_file_path);
921 continue;
922 }
923 else if (errno(*__errno_location ()) == ENOTDIR20 || errno(*__errno_location ()) == ENOENT2)
924 {
925 char *sep = strrchr (state_file_path, G_DIR_SEPARATOR'/');
926
927 *sep = '\0';
928 if (g_mkdir_with_parents (state_file_path, 0755) != 0)
929 {
930 g_warning ("Could not create directory '%s'",
931 state_file_path);
932 g_free (state_file_path);
933 state_file_path = NULL((void*)0);
934 break;
935 }
936
937 continue;
938 }
939
940 g_warning ("Could not create file '%s': %s",
941 state_file_path, g_strerror (errno(*__errno_location ())));
942 g_free (state_file_path);
943 state_file_path = NULL((void*)0);
944 break;
945 }
946
947 close (fd);
948 g_file_set_contents (state_file_path, data, -1, NULL((void*)0));
949 break;
950 }
951 g_free (data);
952
953 restart = generate_command (xsmp->restart_command, xsmp->client_id,
954 state_file_path);
955 set_properties (xsmp,
956 ptrarray_prop (SmRestartCommand"RestartCommand", restart),
957 NULL((void*)0));
958 g_ptr_array_free (restart, TRUE(!(0)));
959
960 if (state_file_path)
961 {
962 set_properties (xsmp,
963 array_prop (SmDiscardCommand"DiscardCommand",
964 "/bin/rm", "-rf", state_file_path,
965 NULL((void*)0)),
966 NULL((void*)0));
967 g_free (state_file_path);
968 }
969}
970
971static void
972xsmp_interact (SmcConn smc_conn,
973 SmPointer client_data)
974{
975 EggSMClientXSMP *xsmp = client_data;
976 EggSMClient *client = client_data;
977
978 g_debug ("Received Interact message in state %s",
979 EGG_SM_CLIENT_XSMP_STATE (xsmp)(state_names[(xsmp)->state]));
980
981 if (xsmp->state != XSMP_STATE_INTERACT_REQUEST)
982 {
983 fix_broken_state (xsmp, "Interact", TRUE(!(0)), TRUE(!(0)));
984 return;
985 }
986
987 xsmp->state = XSMP_STATE_INTERACT;
988 egg_sm_client_quit_requested (client);
989}
990
991static void
992xsmp_die (SmcConn smc_conn,
993 SmPointer client_data)
994{
995 EggSMClientXSMP *xsmp = client_data;
996 EggSMClient *client = client_data;
997
998 g_debug ("Received Die message in state %s",
999 EGG_SM_CLIENT_XSMP_STATE (xsmp)(state_names[(xsmp)->state]));
1000
1001 sm_client_xsmp_disconnect (xsmp);
1002 egg_sm_client_quit (client);
1003}
1004
1005static void
1006xsmp_save_complete (SmcConn smc_conn,
1007 SmPointer client_data)
1008{
1009 EggSMClientXSMP *xsmp = client_data;
1010
1011 g_debug ("Received SaveComplete message in state %s",
1012 EGG_SM_CLIENT_XSMP_STATE (xsmp)(state_names[(xsmp)->state]));
1013
1014 if (xsmp->state == XSMP_STATE_SAVE_YOURSELF_DONE)
1015 xsmp->state = XSMP_STATE_IDLE;
1016 else
1017 fix_broken_state (xsmp, "SaveComplete", FALSE(0), FALSE(0));
1018}
1019
1020static void
1021xsmp_shutdown_cancelled (SmcConn smc_conn,
1022 SmPointer client_data)
1023{
1024 EggSMClientXSMP *xsmp = client_data;
1025 EggSMClient *client = client_data;
1026
1027 g_debug ("Received ShutdownCancelled message in state %s",
1028 EGG_SM_CLIENT_XSMP_STATE (xsmp)(state_names[(xsmp)->state]));
1029
1030 xsmp->shutting_down = FALSE(0);
1031
1032 if (xsmp->state == XSMP_STATE_SAVE_YOURSELF_DONE)
1033 {
1034 /* We've finished interacting and now the SM has agreed to
1035 * cancel the shutdown.
1036 */
1037 xsmp->state = XSMP_STATE_IDLE;
1038 egg_sm_client_quit_cancelled (client);
1039 }
1040 else if (xsmp->state == XSMP_STATE_SHUTDOWN_CANCELLED)
1041 {
1042 /* Hm... ok, so we got a shutdown SaveYourself, which got
1043 * cancelled, but the application was still interacting, so we
1044 * didn't tell it yet, and then *another* SaveYourself arrived,
1045 * which we must still be waiting to tell the app about, except
1046 * that now that SaveYourself has been cancelled too! Dizzy yet?
1047 */
1048 xsmp->waiting_to_save_myself = FALSE(0);
1049 update_pending_events (xsmp);
1050 }
1051 else
1052 {
1053 g_debug ("Sending SaveYourselfDone(False)");
1054 SmcSaveYourselfDone (xsmp->connection, False0);
1055
1056 if (xsmp->state == XSMP_STATE_INTERACT)
1057 {
1058 /* The application is currently interacting, so we can't
1059 * tell it about the cancellation yet; we will wait until
1060 * after it calls egg_sm_client_will_quit().
1061 */
1062 xsmp->state = XSMP_STATE_SHUTDOWN_CANCELLED;
1063 }
1064 else
1065 {
1066 /* The shutdown was cancelled before the application got a
1067 * chance to interact.
1068 */
1069 xsmp->state = XSMP_STATE_IDLE;
1070 }
1071 }
1072}
1073
1074/* Utilities */
1075
1076/* Create a restart/clone/Exec command based on @restart_command.
1077 * If @client_id is non-%NULL, add "--sm-client-id @client_id".
1078 * If @state_file is non-%NULL, add "--sm-client-state-file @state_file".
1079 *
1080 * None of the input strings are g_strdup()ed; the caller must keep
1081 * them around until it is done with the returned GPtrArray, and must
1082 * then free the array, but not its contents.
1083 */
1084static GPtrArray *
1085generate_command (char **restart_command, const char *client_id,
1086 const char *state_file)
1087{
1088 GPtrArray *cmd;
1089 int i;
1090
1091 cmd = g_ptr_array_new ();
1092 g_ptr_array_add (cmd, restart_command[0]);
1093
1094 if (client_id)
1095 {
1096 g_ptr_array_add (cmd, (char *)"--sm-client-id");
1097 g_ptr_array_add (cmd, (char *)client_id);
1098 }
1099
1100 if (state_file)
1101 {
1102 g_ptr_array_add (cmd, (char *)"--sm-client-state-file");
1103 g_ptr_array_add (cmd, (char *)state_file);
1104 }
1105
1106 for (i = 1; restart_command[i]; i++)
1107 g_ptr_array_add (cmd, restart_command[i]);
1108
1109 return cmd;
1110}
1111
1112/* Takes a NULL-terminated list of SmProp * values, created by
1113 * array_prop, ptrarray_prop, string_prop, card8_prop, sets them, and
1114 * frees them.
1115 */
1116static void
1117set_properties (EggSMClientXSMP *xsmp, ...)
1118{
1119 GPtrArray *props;
1120 SmProp *prop;
1121 va_list ap;
1122 guint i;
1123
1124 props = g_ptr_array_new ();
1125
1126 va_start (ap, xsmp)__builtin_va_start(ap, xsmp);
1127 while ((prop = va_arg (ap, SmProp *)__builtin_va_arg(ap, SmProp *)))
1128 g_ptr_array_add (props, prop);
1129 va_end (ap)__builtin_va_end(ap);
1130
1131 if (xsmp->connection)
1132 {
1133 SmcSetProperties (xsmp->connection, props->len,
1134 (SmProp **)props->pdata);
1135 }
1136
1137 for (i = 0; i < props->len; i++)
1138 {
1139 prop = props->pdata[i];
1140 g_free (prop->vals);
1141 g_free (prop);
1142 }
1143 g_ptr_array_free (props, TRUE(!(0)));
1144}
1145
1146/* Takes a NULL-terminated list of property names and deletes them. */
1147static void
1148delete_properties (EggSMClientXSMP *xsmp, ...)
1149{
1150 GPtrArray *props;
1151 char *prop;
1152 va_list ap;
1153
1154 if (!xsmp->connection)
1155 return;
1156
1157 props = g_ptr_array_new ();
1158
1159 va_start (ap, xsmp)__builtin_va_start(ap, xsmp);
1160 while ((prop = va_arg (ap, char *)__builtin_va_arg(ap, char *)))
1161 g_ptr_array_add (props, prop);
1162 va_end (ap)__builtin_va_end(ap);
1163
1164 SmcDeleteProperties (xsmp->connection, props->len,
1165 (char **)props->pdata);
1166
1167 g_ptr_array_free (props, TRUE(!(0)));
1168}
1169
1170/* Takes an array of strings and creates a LISTofARRAY8 property. The
1171 * strings are neither dupped nor freed; they need to remain valid
1172 * until you're done with the SmProp.
1173 */
1174static SmProp *
1175array_prop (const char *name, ...)
1176{
1177 SmProp *prop;
1178 SmPropValue pv;
1179 GArray *vals;
1180 char *value;
1181 va_list ap;
1182
1183 prop = g_new (SmProp, 1)(SmProp *) (__extension__ ({ gsize __n = (gsize) (1); gsize __s
= sizeof (SmProp); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
1184 prop->name = (char *)name;
1185 prop->type = (char *)SmLISTofARRAY8"LISTofARRAY8";
1186
1187 vals = g_array_new (FALSE(0), FALSE(0), sizeof (SmPropValue));
1188
1189 va_start (ap, name)__builtin_va_start(ap, name);
1190 while ((value = va_arg (ap, char *)__builtin_va_arg(ap, char *)))
1191 {
1192 pv.length = strlen (value);
1193 pv.value = value;
1194 g_array_append_val (vals, pv)g_array_append_vals (vals, &(pv), 1);
1195 }
1196 va_end (ap)__builtin_va_end(ap);
1197
1198 prop->num_vals = vals->len;
1199 prop->vals = (SmPropValue *)vals->data;
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
1200
1201 g_array_free (vals, FALSE(0));
1202
1203 return prop;
1204}
1205
1206/* Takes a GPtrArray of strings and creates a LISTofARRAY8 property.
1207 * The array contents are neither dupped nor freed; they need to
1208 * remain valid until you're done with the SmProp.
1209 */
1210static SmProp *
1211ptrarray_prop (const char *name, GPtrArray *values)
1212{
1213 SmProp *prop;
1214 SmPropValue pv;
1215 GArray *vals;
1216 guint i;
1217
1218 prop = g_new (SmProp, 1)(SmProp *) (__extension__ ({ gsize __n = (gsize) (1); gsize __s
= sizeof (SmProp); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
1219 prop->name = (char *)name;
1220 prop->type = (char *)SmLISTofARRAY8"LISTofARRAY8";
1221
1222 vals = g_array_new (FALSE(0), FALSE(0), sizeof (SmPropValue));
1223
1224 for (i = 0; i < values->len; i++)
1225 {
1226 pv.length = strlen (values->pdata[i]);
1227 pv.value = values->pdata[i];
1228 g_array_append_val (vals, pv)g_array_append_vals (vals, &(pv), 1);
1229 }
1230
1231 prop->num_vals = vals->len;
1232 prop->vals = (SmPropValue *)vals->data;
1233
1234 g_array_free (vals, FALSE(0));
1235
1236 return prop;
1237}
1238
1239/* Takes a string and creates an ARRAY8 property. The string is
1240 * neither dupped nor freed; it needs to remain valid until you're
1241 * done with the SmProp.
1242 */
1243static SmProp *
1244string_prop (const char *name, const char *value)
1245{
1246 SmProp *prop;
1247
1248 prop = g_new (SmProp, 1)(SmProp *) (__extension__ ({ gsize __n = (gsize) (1); gsize __s
= sizeof (SmProp); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
1249 prop->name = (char *)name;
1250 prop->type = (char *)SmARRAY8"ARRAY8";
1251
1252 prop->num_vals = 1;
1253 prop->vals = g_new (SmPropValue, 1)(SmPropValue *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (SmPropValue); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
1254
1255 prop->vals[0].length = strlen (value);
1256 prop->vals[0].value = (char *)value;
1257
1258 return prop;
1259}
1260
1261/* Takes a char and creates a CARD8 property. */
1262static SmProp *
1263card8_prop (const char *name, unsigned char value)
1264{
1265 SmProp *prop;
1266 char *card8val;
1267
1268 /* To avoid having to allocate and free prop->vals[0], we cheat and
1269 * make vals a 2-element-long array and then use the second element
1270 * to store value.
1271 */
1272
1273 prop = g_new (SmProp, 1)(SmProp *) (__extension__ ({ gsize __n = (gsize) (1); gsize __s
= sizeof (SmProp); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
1274 prop->name = (char *)name;
1275 prop->type = (char *)SmCARD8"CARD8";
1276
1277 prop->num_vals = 1;
1278 prop->vals = g_new (SmPropValue, 2)(SmPropValue *) (__extension__ ({ gsize __n = (gsize) (2); gsize
__s = sizeof (SmPropValue); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
1279 card8val = (char *)(&prop->vals[1]);
1280 card8val[0] = value;
1281
1282 prop->vals[0].length = 1;
1283 prop->vals[0].value = card8val;
1284
1285 return prop;
1286}
1287
1288/* ICE code. This makes no effort to play nice with anyone else trying
1289 * to use libICE. Fortunately, no one uses libICE for anything other
1290 * than SM. (DCOP uses ICE, but it has its own private copy of
1291 * libICE.)
1292 *
1293 * When this moves to gtk, it will need to be cleverer, to avoid
1294 * tripping over old apps that use MateClient or that use libSM
1295 * directly.
1296 */
1297
1298#include <X11/ICE/ICElib.h>
1299#include <fcntl.h>
1300
1301static void ice_error_handler (IceConn ice_conn,
1302 Boolint swap,
1303 int offending_minor_opcode,
1304 unsigned long offending_sequence,
1305 int error_class,
1306 int severity,
1307 IcePointer values);
1308static void ice_io_error_handler (IceConn ice_conn);
1309static void ice_connection_watch (IceConn ice_conn,
1310 IcePointer client_data,
1311 Boolint opening,
1312 IcePointer *watch_data);
1313
1314static void
1315ice_init (void)
1316{
1317 IceSetIOErrorHandler (ice_io_error_handler);
1318 IceSetErrorHandler (ice_error_handler);
1319 IceAddConnectionWatch (ice_connection_watch, NULL((void*)0));
1320}
1321
1322static gboolean
1323process_ice_messages (IceConn ice_conn)
1324{
1325 IceProcessMessagesStatus status;
1326 status = IceProcessMessages (ice_conn, NULL((void*)0), NULL((void*)0));
1327
1328 switch (status)
1329 {
1330 case IceProcessMessagesSuccess:
1331 return TRUE(!(0));
1332
1333 case IceProcessMessagesIOError:
1334 sm_client_xsmp_disconnect (IceGetConnectionContext (ice_conn));
1335 return FALSE(0);
1336
1337 case IceProcessMessagesConnectionClosed:
1338 return FALSE(0);
1339
1340 default:
1341 g_assert_not_reached ()do { g_assertion_message_expr ("EggSMClient", "eggsmclient-xsmp.c"
, 1341, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1342 }
1343}
1344
1345static gboolean
1346ice_iochannel_watch (GIOChannel *channel,
1347 GIOCondition condition,
1348 gpointer client_data)
1349{
1350 return process_ice_messages (client_data);
1351}
1352
1353static void
1354ice_connection_watch (IceConn ice_conn,
1355 IcePointer client_data,
1356 Boolint opening,
1357 IcePointer *watch_data)
1358{
1359 guint watch_id;
1360
1361 if (opening)
1362 {
1363 GIOChannel *channel;
1364 int fd = IceConnectionNumber (ice_conn);
1365
1366 fcntl (fd, F_SETFD2, fcntl (fd, F_GETFD1, 0) | FD_CLOEXEC1);
1367 channel = g_io_channel_unix_new (fd);
1368 watch_id = g_io_add_watch (channel, G_IO_IN | G_IO_ERR,
1369 ice_iochannel_watch, ice_conn);
1370 g_io_channel_unref (channel);
1371
1372 *watch_data = GUINT_TO_POINTER (watch_id)((gpointer) (gulong) (watch_id));
1373 }
1374 else
1375 {
1376 watch_id = GPOINTER_TO_UINT (*watch_data)((guint) (gulong) (*watch_data));
1377 g_source_remove (watch_id);
1378 }
1379}
1380
1381static void
1382ice_error_handler (IceConn ice_conn,
1383 Boolint swap,
1384 int offending_minor_opcode,
1385 unsigned long offending_sequence,
1386 int error_class,
1387 int severity,
1388 IcePointer values)
1389{
1390 /* Do nothing */
1391}
1392
1393static void
1394ice_io_error_handler (IceConn ice_conn)
1395{
1396 /* Do nothing */
1397}
1398
1399static void
1400smc_error_handler (SmcConn smc_conn,
1401 Boolint swap,
1402 int offending_minor_opcode,
1403 unsigned long offending_sequence,
1404 int error_class,
1405 int severity,
1406 SmPointer values)
1407{
1408 /* Do nothing */
1409}
diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-cf3974.html b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-cf3974.html new file mode 100644 index 00000000..8ec6d5ff --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-cf3974.html @@ -0,0 +1,2089 @@ + + + +eggsmclient-xsmp.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:pluma/mate-submodules/libegg/eggsmclient-xsmp.c
Warning:line 1232, column 18
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name eggsmclient-xsmp.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/pluma/mate-submodules/libegg -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I ../../.. -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -D EGG_SM_CLIENT_BACKEND_XSMP -D G_LOG_DOMAIN="EggSMClient" -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/pluma/mate-submodules/libegg -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-10-22-114445-13211-1 -x c eggsmclient-xsmp.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright (C) 2007 Novell, Inc.
3 *
4 * Inspired by various other pieces of code including GsmClient (C)
5 * 2001 Havoc Pennington, MateClient (C) 1998 Carsten Schaar, and twm
6 * session code (C) 1998 The Open Group.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24#include "config.h"
25
26#include "eggsmclient.h"
27#include "eggsmclient-private.h"
28
29#include "eggdesktopfile.h"
30
31#include <errno(*__errno_location ()).h>
32#include <fcntl.h>
33#include <stdlib.h>
34#include <string.h>
35#include <unistd.h>
36#include <X11/SM/SMlib.h>
37
38#include <gtk/gtk.h>
39#include <gdk/gdk.h>
40
41#if defined(GDK_WINDOWING_X11) || defined(HAVE_X11)
42#include <gdk/gdkx.h>
43#endif
44
45#define EGG_TYPE_SM_CLIENT_XSMP(egg_sm_client_xsmp_get_type ()) (egg_sm_client_xsmp_get_type ())
46#define EGG_SM_CLIENT_XSMP(obj)((((EggSMClientXSMP*) (void *) ((obj))))) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SM_CLIENT_XSMP, EggSMClientXSMP)(((EggSMClientXSMP*) (void *) ((obj)))))
47#define EGG_SM_CLIENT_XSMP_CLASS(klass)((((EggSMClientXSMPClass*) (void *) ((klass))))) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SM_CLIENT_XSMP, EggSMClientXSMPClass)(((EggSMClientXSMPClass*) (void *) ((klass)))))
48#define EGG_IS_SM_CLIENT_XSMP(obj)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(obj)); GType __t = ((egg_sm_client_xsmp_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; }))))
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SM_CLIENT_XSMP)((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(obj)); GType __t = ((egg_sm_client_xsmp_get_type ())); gboolean
__r; if (!__inst) __r = (0); else if (__inst->g_class &&
__inst->g_class->g_type == __t) __r = (!(0)); else __r
= g_type_check_instance_is_a (__inst, __t); __r; })))
)
49#define EGG_IS_SM_CLIENT_XSMP_CLASS(klass)(((__extension__ ({ GTypeClass *__class = (GTypeClass*) ((klass
)); GType __t = ((egg_sm_client_xsmp_get_type ())); gboolean __r
; if (!__class) __r = (0); else if (__class->g_type == __t
) __r = (!(0)); else __r = g_type_check_class_is_a (__class, __t
); __r; }))))
(G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SM_CLIENT_XSMP)((__extension__ ({ GTypeClass *__class = (GTypeClass*) ((klass
)); GType __t = ((egg_sm_client_xsmp_get_type ())); gboolean __r
; if (!__class) __r = (0); else if (__class->g_type == __t
) __r = (!(0)); else __r = g_type_check_class_is_a (__class, __t
); __r; })))
)
50#define EGG_SM_CLIENT_XSMP_GET_CLASS(obj)((((EggSMClientXSMPClass*) (((GTypeInstance*) ((obj)))->g_class
))))
(G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SM_CLIENT_XSMP, EggSMClientXSMPClass)(((EggSMClientXSMPClass*) (((GTypeInstance*) ((obj)))->g_class
)))
)
51
52typedef struct _EggSMClientXSMP EggSMClientXSMP;
53typedef struct _EggSMClientXSMPClass EggSMClientXSMPClass;
54
55/* These mostly correspond to the similarly-named states in section
56 * 9.1 of the XSMP spec. Some of the states there aren't represented
57 * here, because we don't need them. SHUTDOWN_CANCELLED is slightly
58 * different from the spec; we use it when the client is IDLE after a
59 * ShutdownCancelled message, but the application is still interacting
60 * and doesn't know the shutdown has been cancelled yet.
61 */
62typedef enum
63{
64 XSMP_STATE_IDLE,
65 XSMP_STATE_SAVE_YOURSELF,
66 XSMP_STATE_INTERACT_REQUEST,
67 XSMP_STATE_INTERACT,
68 XSMP_STATE_SAVE_YOURSELF_DONE,
69 XSMP_STATE_SHUTDOWN_CANCELLED,
70 XSMP_STATE_CONNECTION_CLOSED
71} EggSMClientXSMPState;
72
73static const char *state_names[] =
74{
75 "idle",
76 "save-yourself",
77 "interact-request",
78 "interact",
79 "save-yourself-done",
80 "shutdown-cancelled",
81 "connection-closed"
82};
83
84#define EGG_SM_CLIENT_XSMP_STATE(xsmp)(state_names[(xsmp)->state]) (state_names[(xsmp)->state])
85
86struct _EggSMClientXSMP
87{
88 EggSMClient parent;
89
90 SmcConn connection;
91 char *client_id;
92
93 EggSMClientXSMPState state;
94 char **restart_command;
95 gboolean set_restart_command;
96 int restart_style;
97 char **discard_command;
98 gboolean set_discard_command;
99
100 guint idle;
101
102 /* Current SaveYourself state */
103 guint expecting_initial_save_yourself : 1;
104 guint need_save_state : 1;
105 guint need_quit_requested : 1;
106 guint interact_errors : 1;
107 guint shutting_down : 1;
108
109 /* Todo list */
110 guint waiting_to_set_initial_properties : 1;
111 guint waiting_to_emit_quit : 1;
112 guint waiting_to_emit_quit_cancelled : 1;
113 guint waiting_to_save_myself : 1;
114
115};
116
117struct _EggSMClientXSMPClass
118{
119 EggSMClientClass parent_class;
120
121};
122
123static void sm_client_xsmp_startup (EggSMClient *client,
124 const char *client_id);
125static void sm_client_xsmp_set_restart_command (EggSMClient *client,
126 int argc,
127 const char **argv);
128static void sm_client_xsmp_set_discard_command (EggSMClient *client,
129 int argc,
130 const char **argv);
131static void sm_client_xsmp_will_quit (EggSMClient *client,
132 gboolean will_quit);
133static gboolean sm_client_xsmp_end_session (EggSMClient *client,
134 EggSMClientEndStyle style,
135 gboolean request_confirmation);
136
137static void xsmp_save_yourself (SmcConn smc_conn,
138 SmPointer client_data,
139 int save_style,
140 Boolint shutdown,
141 int interact_style,
142 Boolint fast);
143static void xsmp_die (SmcConn smc_conn,
144 SmPointer client_data);
145static void xsmp_save_complete (SmcConn smc_conn,
146 SmPointer client_data);
147static void xsmp_shutdown_cancelled (SmcConn smc_conn,
148 SmPointer client_data);
149static void xsmp_interact (SmcConn smc_conn,
150 SmPointer client_data);
151
152static SmProp *array_prop (const char *name,
153 ...);
154static SmProp *ptrarray_prop (const char *name,
155 GPtrArray *values);
156static SmProp *string_prop (const char *name,
157 const char *value);
158static SmProp *card8_prop (const char *name,
159 unsigned char value);
160
161static void set_properties (EggSMClientXSMP *xsmp, ...);
162static void delete_properties (EggSMClientXSMP *xsmp, ...);
163
164static GPtrArray *generate_command (char **restart_command,
165 const char *client_id,
166 const char *state_file);
167
168static void save_state (EggSMClientXSMP *xsmp);
169static void do_save_yourself (EggSMClientXSMP *xsmp);
170static void update_pending_events (EggSMClientXSMP *xsmp);
171
172static void ice_init (void);
173static gboolean process_ice_messages (IceConn ice_conn);
174static void smc_error_handler (SmcConn smc_conn,
175 Boolint swap,
176 int offending_minor_opcode,
177 unsigned long offending_sequence,
178 int error_class,
179 int severity,
180 SmPointer values);
181
182G_DEFINE_TYPE (EggSMClientXSMP, egg_sm_client_xsmp, EGG_TYPE_SM_CLIENT)static void egg_sm_client_xsmp_init (EggSMClientXSMP *self); static
void egg_sm_client_xsmp_class_init (EggSMClientXSMPClass *klass
); static GType egg_sm_client_xsmp_get_type_once (void); static
gpointer egg_sm_client_xsmp_parent_class = ((void*)0); static
gint EggSMClientXSMP_private_offset; static void egg_sm_client_xsmp_class_intern_init
(gpointer klass) { egg_sm_client_xsmp_parent_class = g_type_class_peek_parent
(klass); if (EggSMClientXSMP_private_offset != 0) g_type_class_adjust_private_offset
(klass, &EggSMClientXSMP_private_offset); egg_sm_client_xsmp_class_init
((EggSMClientXSMPClass*) klass); } __attribute__ ((__unused__
)) static inline gpointer egg_sm_client_xsmp_get_instance_private
(EggSMClientXSMP *self) { return (((gpointer) ((guint8*) (self
) + (glong) (EggSMClientXSMP_private_offset)))); } GType egg_sm_client_xsmp_get_type
(void) { static gsize static_g_define_type_id = 0; if ((__extension__
({ _Static_assert (sizeof *(&static_g_define_type_id) ==
sizeof (gpointer), "Expression evaluates to false"); (void) (
0 ? (gpointer) *(&static_g_define_type_id) : ((void*)0));
(!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); __typeof__
(*(&static_g_define_type_id)) gapg_temp_newval; __typeof__
((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id
); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5)
; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id
)); }))) { GType g_define_type_id = egg_sm_client_xsmp_get_type_once
(); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id
) == sizeof (gpointer), "Expression evaluates to false"); 0 ?
(void) (*(&static_g_define_type_id) = (g_define_type_id)
) : (void) 0; g_once_init_leave ((&static_g_define_type_id
), (gsize) (g_define_type_id)); })); } return static_g_define_type_id
; } __attribute__ ((__noinline__)) static GType egg_sm_client_xsmp_get_type_once
(void) { GType g_define_type_id = g_type_register_static_simple
((egg_sm_client_get_type ()), g_intern_static_string ("EggSMClientXSMP"
), sizeof (EggSMClientXSMPClass), (GClassInitFunc)(void (*)(void
)) egg_sm_client_xsmp_class_intern_init, sizeof (EggSMClientXSMP
), (GInstanceInitFunc)(void (*)(void)) egg_sm_client_xsmp_init
, (GTypeFlags) 0); { {{};} } return g_define_type_id; }
183
184static void
185egg_sm_client_xsmp_init (EggSMClientXSMP *xsmp)
186{
187 xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
188 xsmp->connection = NULL((void*)0);
189 xsmp->restart_style = SmRestartIfRunning0;
190}
191
192static void
193egg_sm_client_xsmp_class_init (EggSMClientXSMPClass *klass)
194{
195 EggSMClientClass *sm_client_class = EGG_SM_CLIENT_CLASS (klass);
196
197 sm_client_class->startup = sm_client_xsmp_startup;
198 sm_client_class->set_restart_command = sm_client_xsmp_set_restart_command;
199 sm_client_class->set_discard_command = sm_client_xsmp_set_discard_command;
200 sm_client_class->will_quit = sm_client_xsmp_will_quit;
201 sm_client_class->end_session = sm_client_xsmp_end_session;
202}
203
204EggSMClient *
205egg_sm_client_xsmp_new (void)
206{
207 if (!g_getenv ("SESSION_MANAGER"))
208 return NULL((void*)0);
209
210 return g_object_new (EGG_TYPE_SM_CLIENT_XSMP(egg_sm_client_xsmp_get_type ()), NULL((void*)0));
211}
212
213static gboolean
214sm_client_xsmp_set_initial_properties (gpointer user_data)
215{
216 EggSMClientXSMP *xsmp = user_data;
217 EggDesktopFile *desktop_file;
218 GPtrArray *clone, *restart;
219 char pid_str[64];
220
221 if (xsmp->idle)
222 {
223 g_source_remove (xsmp->idle);
224 xsmp->idle = 0;
225 }
226 xsmp->waiting_to_set_initial_properties = FALSE(0);
227
228 if (egg_sm_client_get_mode () == EGG_SM_CLIENT_MODE_NO_RESTART)
229 xsmp->restart_style = SmRestartNever3;
230
231 /* Parse info out of desktop file */
232 desktop_file = egg_get_desktop_file ();
233 if (desktop_file)
234 {
235 GError *err = NULL((void*)0);
236 char **argv;
237 int argc;
238
239 if (xsmp->restart_style == SmRestartIfRunning0)
240 {
241 if (egg_desktop_file_get_boolean (desktop_file,
242 "X-MATE-AutoRestart", NULL((void*)0)))
243 xsmp->restart_style = SmRestartImmediately2;
244 }
245
246 if (!xsmp->set_restart_command)
247 {
248 char *cmdline;
249
250 cmdline = egg_desktop_file_parse_exec (desktop_file, NULL((void*)0), &err);
251 if (cmdline && g_shell_parse_argv (cmdline, &argc, &argv, &err))
252 {
253 egg_sm_client_set_restart_command (EGG_SM_CLIENT (xsmp),
254 argc, (const char **)argv);
255 g_strfreev (argv);
256 }
257 else
258 {
259 g_warning ("Could not parse Exec line in desktop file: %s",
260 err->message);
261 g_error_free (err);
262 }
263 g_free (cmdline);
264 }
265 }
266
267 if (!xsmp->set_restart_command)
268 xsmp->restart_command = g_strsplit (g_get_prgname (), " ", -1);
269
270 clone = generate_command (xsmp->restart_command, NULL((void*)0), NULL((void*)0));
271 restart = generate_command (xsmp->restart_command, xsmp->client_id, NULL((void*)0));
272
273 g_debug ("Setting initial properties");
274
275 /* Program, CloneCommand, RestartCommand, and UserID are required.
276 * ProcessID isn't required, but the SM may be able to do something
277 * useful with it.
278 */
279 g_snprintf (pid_str, sizeof (pid_str), "%lu", (gulong) getpid ());
280 set_properties (xsmp,
281 string_prop (SmProgram"Program", g_get_prgname ()),
282 ptrarray_prop (SmCloneCommand"CloneCommand", clone),
283 ptrarray_prop (SmRestartCommand"RestartCommand", restart),
284 string_prop (SmUserID"UserID", g_get_user_name ()),
285 string_prop (SmProcessID"ProcessID", pid_str),
286 card8_prop (SmRestartStyleHint"RestartStyleHint", xsmp->restart_style),
287 NULL((void*)0));
288 g_ptr_array_free (clone, TRUE(!(0)));
289 g_ptr_array_free (restart, TRUE(!(0)));
290
291 if (desktop_file)
292 {
293 set_properties (xsmp,
294 string_prop ("_GSM_DesktopFile", egg_desktop_file_get_source (desktop_file)),
295 NULL((void*)0));
296 }
297
298 update_pending_events (xsmp);
299 return FALSE(0);
300}
301
302/* This gets called from two different places: xsmp_die() (when the
303 * server asks us to disconnect) and process_ice_messages() (when the
304 * server disconnects unexpectedly).
305 */
306static void
307sm_client_xsmp_disconnect (EggSMClientXSMP *xsmp)
308{
309 SmcConn connection;
310
311 if (!xsmp->connection)
312 return;
313
314 g_debug ("Disconnecting");
315
316 connection = xsmp->connection;
317 xsmp->connection = NULL((void*)0);
318 SmcCloseConnection (connection, 0, NULL((void*)0));
319 xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
320
321 xsmp->waiting_to_save_myself = FALSE(0);
322 update_pending_events (xsmp);
323}
324
325static void
326sm_client_xsmp_startup (EggSMClient *client,
327 const char *client_id)
328{
329 EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
330 SmcCallbacks callbacks;
331 char *ret_client_id;
332 char error_string_ret[256];
333
334 xsmp->client_id = g_strdup (client_id)g_strdup_inline (client_id);
335
336 ice_init ();
337 SmcSetErrorHandler (smc_error_handler);
338
339 callbacks.save_yourself.callback = xsmp_save_yourself;
340 callbacks.die.callback = xsmp_die;
341 callbacks.save_complete.callback = xsmp_save_complete;
342 callbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
343
344 callbacks.save_yourself.client_data = xsmp;
345 callbacks.die.client_data = xsmp;
346 callbacks.save_complete.client_data = xsmp;
347 callbacks.shutdown_cancelled.client_data = xsmp;
348
349 client_id = NULL((void*)0);
350 error_string_ret[0] = '\0';
351 xsmp->connection =
352 SmcOpenConnection (NULL((void*)0), xsmp, SmProtoMajor1, SmProtoMinor0,
353 SmcSaveYourselfProcMask(1L << 0) | SmcDieProcMask(1L << 1) |
354 SmcSaveCompleteProcMask(1L << 2) |
355 SmcShutdownCancelledProcMask(1L << 3),
356 &callbacks,
357 xsmp->client_id, &ret_client_id,
358 sizeof (error_string_ret), error_string_ret);
359
360 if (!xsmp->connection)
361 {
362 g_warning ("Failed to connect to the session manager: %s\n",
363 error_string_ret[0] ?
364 error_string_ret : "no error message given");
365 xsmp->state = XSMP_STATE_CONNECTION_CLOSED;
366 return;
367 }
368
369 /* We expect a pointless initial SaveYourself if either (a) we
370 * didn't have an initial client ID, or (b) we DID have an initial
371 * client ID, but the server rejected it and gave us a new one.
372 */
373 if (!xsmp->client_id ||
374 (ret_client_id && strcmp (xsmp->client_id, ret_client_id) != 0))
375 xsmp->expecting_initial_save_yourself = TRUE(!(0));
376
377 if (ret_client_id)
378 {
379 g_free (xsmp->client_id);
380 xsmp->client_id = g_strdup (ret_client_id)g_strdup_inline (ret_client_id);
381 free (ret_client_id);
382
383#if defined(GDK_WINDOWING_X11) || defined(HAVE_X11)
384 if (GDK_IS_X11_DISPLAY (gdk_display_get_default ())(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (
(gdk_display_get_default ())); GType __t = ((gdk_x11_display_get_type
())); gboolean __r; if (!__inst) __r = (0); else if (__inst->
g_class && __inst->g_class->g_type == __t) __r =
(!(0)); else __r = g_type_check_instance_is_a (__inst, __t);
__r; }))))
)
385 gdk_x11_set_sm_client_id (xsmp->client_id);
386#endif
387
388 g_debug ("Got client ID \"%s\"", xsmp->client_id);
389 }
390
391 xsmp->state = XSMP_STATE_IDLE;
392
393 /* Do not set the initial properties until we reach the main loop,
394 * so that the application has a chance to call
395 * egg_set_desktop_file(). (This may also help the session manager
396 * have a better idea of when the application is fully up and
397 * running.)
398 */
399 xsmp->waiting_to_set_initial_properties = TRUE(!(0));
400 xsmp->idle = g_idle_add (sm_client_xsmp_set_initial_properties, client);
401}
402
403static void
404sm_client_xsmp_set_restart_command (EggSMClient *client,
405 int argc,
406 const char **argv)
407{
408 EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
409 int i;
410
411 g_strfreev (xsmp->restart_command);
412
413 xsmp->restart_command = g_new (char *, argc + 1)(char * *) (__extension__ ({ gsize __n = (gsize) (argc + 1); gsize
__s = sizeof (char *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
414 for (i = 0; i < argc; i++)
415 xsmp->restart_command[i] = g_strdup (argv[i])g_strdup_inline (argv[i]);
416 xsmp->restart_command[i] = NULL((void*)0);
417
418 xsmp->set_restart_command = TRUE(!(0));
419}
420
421static void
422sm_client_xsmp_set_discard_command (EggSMClient *client,
423 int argc,
424 const char **argv)
425{
426 EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
427 int i;
428
429 g_strfreev (xsmp->discard_command);
430
431 xsmp->discard_command = g_new (char *, argc + 1)(char * *) (__extension__ ({ gsize __n = (gsize) (argc + 1); gsize
__s = sizeof (char *); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
432 for (i = 0; i < argc; i++)
433 xsmp->discard_command[i] = g_strdup (argv[i])g_strdup_inline (argv[i]);
434 xsmp->discard_command[i] = NULL((void*)0);
435
436 xsmp->set_discard_command = TRUE(!(0));
437}
438
439static void
440sm_client_xsmp_will_quit (EggSMClient *client,
441 gboolean will_quit)
442{
443 EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
444
445 if (xsmp->state == XSMP_STATE_CONNECTION_CLOSED)
446 {
447 /* The session manager has already exited! Schedule a quit
448 * signal.
449 */
450 xsmp->waiting_to_emit_quit = TRUE(!(0));
451 update_pending_events (xsmp);
452 return;
453 }
454 else if (xsmp->state == XSMP_STATE_SHUTDOWN_CANCELLED)
455 {
456 /* We received a ShutdownCancelled message while the application
457 * was interacting; Schedule a quit_cancelled signal.
458 */
459 xsmp->waiting_to_emit_quit_cancelled = TRUE(!(0));
460 update_pending_events (xsmp);
461 return;
462 }
463
464 g_return_if_fail (xsmp->state == XSMP_STATE_INTERACT)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_12
; if (xsmp->state == XSMP_STATE_INTERACT) _g_boolean_var_12
= 1; else _g_boolean_var_12 = 0; _g_boolean_var_12; }), 1)))
{ } else { g_return_if_fail_warning ("EggSMClient", ((const char
*) (__func__)), "xsmp->state == XSMP_STATE_INTERACT"); return
; } } while (0)
;
465
466 g_debug ("Sending InteractDone(%s)", will_quit ? "False" : "True");
467 SmcInteractDone (xsmp->connection, !will_quit);
468
469 if (will_quit && xsmp->need_save_state)
470 save_state (xsmp);
471
472 g_debug ("Sending SaveYourselfDone(%s)", will_quit ? "True" : "False");
473 SmcSaveYourselfDone (xsmp->connection, will_quit);
474 xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
475}
476
477static gboolean
478sm_client_xsmp_end_session (EggSMClient *client,
479 EggSMClientEndStyle style,
480 gboolean request_confirmation)
481{
482 EggSMClientXSMP *xsmp = (EggSMClientXSMP *)client;
483 int save_type;
484
485 /* To end the session via XSMP, we have to send a
486 * SaveYourselfRequest. We aren't allowed to do that if anything
487 * else is going on, but we don't want to expose this fact to the
488 * application. So we do our best to patch things up here...
489 *
490 * In the worst case, this method might block for some length of
491 * time in process_ice_messages, but the only time that code path is
492 * honestly likely to get hit is if the application tries to end the
493 * session as the very first thing it does, in which case it
494 * probably won't actually block anyway. It's not worth gunking up
495 * the API to try to deal nicely with the other 0.01% of cases where
496 * this happens.
497 */
498
499 while (xsmp->state != XSMP_STATE_IDLE ||
500 xsmp->expecting_initial_save_yourself)
501 {
502 /* If we're already shutting down, we don't need to do anything. */
503 if (xsmp->shutting_down)
504 return TRUE(!(0));
505
506 switch (xsmp->state)
507 {
508 case XSMP_STATE_CONNECTION_CLOSED:
509 return FALSE(0);
510
511 case XSMP_STATE_SAVE_YOURSELF:
512 /* Trying to log out from the save_state callback? Whatever.
513 * Abort the save_state.
514 */
515 SmcSaveYourselfDone (xsmp->connection, FALSE(0));
516 xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
517 break;
518
519 case XSMP_STATE_INTERACT_REQUEST:
520 case XSMP_STATE_INTERACT:
521 case XSMP_STATE_SHUTDOWN_CANCELLED:
522 /* Already in a shutdown-related state, just ignore
523 * the new shutdown request...
524 */
525 return TRUE(!(0));
526
527 case XSMP_STATE_IDLE:
528 if (xsmp->waiting_to_set_initial_properties)
529 sm_client_xsmp_set_initial_properties (xsmp);
530
531 if (!xsmp->expecting_initial_save_yourself)
532 break;
533 /* else fall through */
534
535 case XSMP_STATE_SAVE_YOURSELF_DONE:
536 /* We need to wait for some response from the server.*/
537 process_ice_messages (SmcGetIceConnection (xsmp->connection));
538 break;
539
540 default:
541 /* Hm... shouldn't happen */
542 return FALSE(0);
543 }
544 }
545
546 /* xfce4-session will do the wrong thing if we pass SmSaveGlobal and
547 * the user chooses to save the session. But mate-session will do
548 * the wrong thing if we pass SmSaveBoth and the user chooses NOT to
549 * save the session... Sigh.
550 */
551 if (!strcmp (SmcVendor (xsmp->connection), "xfce4-session"))
552 save_type = SmSaveBoth2;
553 else
554 save_type = SmSaveGlobal0;
555
556 g_debug ("Sending SaveYourselfRequest(SmSaveGlobal, Shutdown, SmInteractStyleAny, %sFast)", request_confirmation ? "!" : "");
557 SmcRequestSaveYourself (xsmp->connection,
558 save_type,
559 True1, /* shutdown */
560 SmInteractStyleAny2,
561 !request_confirmation, /* fast */
562 True1 /* global */);
563 return TRUE(!(0));
564}
565
566static gboolean
567idle_do_pending_events (gpointer data)
568{
569 EggSMClientXSMP *xsmp = data;
570 EggSMClient *client = data;
571
572 xsmp->idle = 0;
573
574 if (xsmp->waiting_to_emit_quit)
575 {
576 xsmp->waiting_to_emit_quit = FALSE(0);
577 egg_sm_client_quit (client);
578 goto out;
579 }
580
581 if (xsmp->waiting_to_emit_quit_cancelled)
582 {
583 xsmp->waiting_to_emit_quit_cancelled = FALSE(0);
584 egg_sm_client_quit_cancelled (client);
585 xsmp->state = XSMP_STATE_IDLE;
586 }
587
588 if (xsmp->waiting_to_save_myself)
589 {
590 xsmp->waiting_to_save_myself = FALSE(0);
591 do_save_yourself (xsmp);
592 }
593
594out:
595 return FALSE(0);
596}
597
598static void
599update_pending_events (EggSMClientXSMP *xsmp)
600{
601 gboolean want_idle =
602 xsmp->waiting_to_emit_quit ||
603 xsmp->waiting_to_emit_quit_cancelled ||
604 xsmp->waiting_to_save_myself;
605
606 if (want_idle)
607 {
608 if (xsmp->idle == 0)
609 xsmp->idle = g_idle_add (idle_do_pending_events, xsmp);
610 }
611 else
612 {
613 if (xsmp->idle != 0)
614 g_source_remove (xsmp->idle);
615 xsmp->idle = 0;
616 }
617}
618
619static void
620fix_broken_state (EggSMClientXSMP *xsmp, const char *message,
621 gboolean send_interact_done,
622 gboolean send_save_yourself_done)
623{
624 g_warning ("Received XSMP %s message in state %s: client or server error",
625 message, EGG_SM_CLIENT_XSMP_STATE (xsmp)(state_names[(xsmp)->state]));
626
627 /* Forget any pending SaveYourself plans we had */
628 xsmp->waiting_to_save_myself = FALSE(0);
629 update_pending_events (xsmp);
630
631 if (send_interact_done)
632 SmcInteractDone (xsmp->connection, False0);
633 if (send_save_yourself_done)
634 SmcSaveYourselfDone (xsmp->connection, True1);
635
636 xsmp->state = send_save_yourself_done ? XSMP_STATE_SAVE_YOURSELF_DONE : XSMP_STATE_IDLE;
637}
638
639/* SM callbacks */
640
641static void
642xsmp_save_yourself (SmcConn smc_conn,
643 SmPointer client_data,
644 int save_type,
645 Boolint shutdown,
646 int interact_style,
647 Boolint fast)
648{
649 EggSMClientXSMP *xsmp = client_data;
650 gboolean wants_quit_requested;
651
652 g_debug ("Received SaveYourself(%s, %s, %s, %s) in state %s",
653 save_type == SmSaveLocal1 ? "SmSaveLocal" :
654 save_type == SmSaveGlobal0 ? "SmSaveGlobal" : "SmSaveBoth",
655 shutdown ? "Shutdown" : "!Shutdown",
656 interact_style == SmInteractStyleAny2 ? "SmInteractStyleAny" :
657 interact_style == SmInteractStyleErrors1 ? "SmInteractStyleErrors" :
658 "SmInteractStyleNone", fast ? "Fast" : "!Fast",
659 EGG_SM_CLIENT_XSMP_STATE (xsmp)(state_names[(xsmp)->state]));
660
661 if (xsmp->state != XSMP_STATE_IDLE &&
662 xsmp->state != XSMP_STATE_SHUTDOWN_CANCELLED)
663 {
664 fix_broken_state (xsmp, "SaveYourself", FALSE(0), TRUE(!(0)));
665 return;
666 }
667
668 if (xsmp->waiting_to_set_initial_properties)
669 sm_client_xsmp_set_initial_properties (xsmp);
670
671 /* If this is the initial SaveYourself, ignore it; we've already set
672 * properties and there's no reason to actually save state too.
673 */
674 if (xsmp->expecting_initial_save_yourself)
675 {
676 xsmp->expecting_initial_save_yourself = FALSE(0);
677
678 if (save_type == SmSaveLocal1 &&
679 interact_style == SmInteractStyleNone0 &&
680 !shutdown && !fast)
681 {
682 g_debug ("Sending SaveYourselfDone(True) for initial SaveYourself");
683 SmcSaveYourselfDone (xsmp->connection, True1);
684 /* As explained in the comment at the end of
685 * do_save_yourself(), SAVE_YOURSELF_DONE is the correct
686 * state here, not IDLE.
687 */
688 xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
689 return;
690 }
691 else
692 g_warning ("First SaveYourself was not the expected one!");
693 }
694
695 /* Even ignoring the "fast" flag completely, there are still 18
696 * different combinations of save_type, shutdown and interact_style.
697 * We interpret them as follows:
698 *
699 * Type Shutdown Interact Interpretation
700 * G F A/E/N do nothing (1)
701 * G T N do nothing (1)*
702 * G T A/E quit_requested (2)
703 * L/B F A/E/N save_state (3)
704 * L/B T N save_state (3)*
705 * L/B T A/E quit_requested, then save_state (4)
706 *
707 * 1. Do nothing, because the SM asked us to do something
708 * uninteresting (save open files, but then don't quit
709 * afterward) or rude (save open files without asking the user
710 * for confirmation).
711 *
712 * 2. Request interaction and then emit ::quit_requested. This
713 * perhaps isn't quite correct for the SmInteractStyleErrors
714 * case, but we don't care.
715 *
716 * 3. Emit ::save_state. The SmSaveBoth SaveYourselfs in these
717 * rows essentially get demoted to SmSaveLocal, because their
718 * Global halves correspond to "do nothing".
719 *
720 * 4. Request interaction, emit ::quit_requested, and then emit
721 * ::save_state after interacting. This is the SmSaveBoth
722 * equivalent of #2, but we also promote SmSaveLocal shutdown
723 * SaveYourselfs to SmSaveBoth here, because we want to give
724 * the user a chance to save open files before quitting.
725 *
726 * (* It would be nice if we could do something useful when the
727 * session manager sends a SaveYourself with shutdown True and
728 * SmInteractStyleNone. But we can't, so we just pretend it didn't
729 * even tell us it was shutting down. The docs for ::quit mention
730 * that it might not always be preceded by ::quit_requested.)
731 */
732
733 /* As an optimization, we don't actually request interaction and
734 * emit ::quit_requested if the application isn't listening to the
735 * signal.
736 */
737 wants_quit_requested = g_signal_has_handler_pending (xsmp, g_signal_lookup ("quit_requested", EGG_TYPE_SM_CLIENT(egg_sm_client_get_type ())), 0, FALSE(0));
738
739 xsmp->need_save_state = (save_type != SmSaveGlobal0);
740 xsmp->need_quit_requested = (shutdown && wants_quit_requested &&
741 interact_style != SmInteractStyleNone0);
742 xsmp->interact_errors = (interact_style == SmInteractStyleErrors1);
743
744 xsmp->shutting_down = shutdown;
745
746 do_save_yourself (xsmp);
747}
748
749static void
750do_save_yourself (EggSMClientXSMP *xsmp)
751{
752 if (xsmp->state == XSMP_STATE_SHUTDOWN_CANCELLED)
753 {
754 /* The SM cancelled a previous SaveYourself, but we haven't yet
755 * had a chance to tell the application, so we can't start
756 * processing this SaveYourself yet.
757 */
758 xsmp->waiting_to_save_myself = TRUE(!(0));
759 update_pending_events (xsmp);
760 return;
761 }
762
763 if (xsmp->need_quit_requested)
764 {
765 xsmp->state = XSMP_STATE_INTERACT_REQUEST;
766
767 g_debug ("Sending InteractRequest(%s)",
768 xsmp->interact_errors ? "Error" : "Normal");
769 SmcInteractRequest (xsmp->connection,
770 xsmp->interact_errors ? SmDialogError0 : SmDialogNormal1,
771 xsmp_interact,
772 xsmp);
773 return;
774 }
775
776 if (xsmp->need_save_state)
777 {
778 save_state (xsmp);
779
780 /* Though unlikely, the client could have been disconnected
781 * while the application was saving its state.
782 */
783 if (!xsmp->connection)
784 return;
785 }
786
787 g_debug ("Sending SaveYourselfDone(True)");
788 SmcSaveYourselfDone (xsmp->connection, True1);
789
790 /* The client state diagram in the XSMP spec says that after a
791 * non-shutdown SaveYourself, we go directly back to "idle". But
792 * everything else in both the XSMP spec and the libSM docs
793 * disagrees.
794 */
795 xsmp->state = XSMP_STATE_SAVE_YOURSELF_DONE;
796}
797
798static void
799save_state (EggSMClientXSMP *xsmp)
800{
801 GKeyFile *state_file;
802 char *state_file_path, *data;
803 EggDesktopFile *desktop_file;
804 GPtrArray *restart, *discard;
805 int offset, fd;
806
807 /* We set xsmp->state before emitting save_state, but our caller is
808 * responsible for setting it back afterward.
809 */
810 xsmp->state = XSMP_STATE_SAVE_YOURSELF;
811
812 state_file = egg_sm_client_save_state ((EggSMClient *)xsmp);
813 if (!state_file)
814 {
815 restart = generate_command (xsmp->restart_command, xsmp->client_id, NULL((void*)0));
816 set_properties (xsmp,
817 ptrarray_prop (SmRestartCommand"RestartCommand", restart),
818 NULL((void*)0));
819 g_ptr_array_free (restart, TRUE(!(0)));
820
821 if (xsmp->set_discard_command)
822 {
823 discard = generate_command (xsmp->discard_command, NULL((void*)0), NULL((void*)0));
824 set_properties (xsmp,
825 ptrarray_prop (SmDiscardCommand"DiscardCommand", discard),
826 NULL((void*)0));
827 g_ptr_array_free (discard, TRUE(!(0)));
828 }
829 else
830 delete_properties (xsmp, SmDiscardCommand"DiscardCommand", NULL((void*)0));
831
832 return;
833 }
834
835 desktop_file = egg_get_desktop_file ();
836 if (desktop_file)
837 {
838 GKeyFile *merged_file;
839 char *desktop_file_path;
840
841 merged_file = g_key_file_new ();
842 desktop_file_path =
843 g_filename_from_uri (egg_desktop_file_get_source (desktop_file),
844 NULL((void*)0), NULL((void*)0));
845 if (desktop_file_path &&
846 g_key_file_load_from_file (merged_file, desktop_file_path,
847 G_KEY_FILE_KEEP_COMMENTS |
848 G_KEY_FILE_KEEP_TRANSLATIONS, NULL((void*)0)))
849 {
850 guint g, k, i;
851 char **groups, **keys, *value, *exec;
852
853 groups = g_key_file_get_groups (state_file, NULL((void*)0));
854 for (g = 0; groups[g]; g++)
855 {
856 keys = g_key_file_get_keys (state_file, groups[g], NULL((void*)0), NULL((void*)0));
857 for (k = 0; keys[k]; k++)
858 {
859 value = g_key_file_get_value (state_file, groups[g],
860 keys[k], NULL((void*)0));
861 if (value)
862 {
863 g_key_file_set_value (merged_file, groups[g],
864 keys[k], value);
865 g_free (value);
866 }
867 }
868 g_strfreev (keys);
869 }
870 g_strfreev (groups);
871
872 g_key_file_free (state_file);
873 state_file = merged_file;
874
875 /* Update Exec key using "--sm-client-state-file %k" */
876 restart = generate_command (xsmp->restart_command,
877 NULL((void*)0), "%k");
878 for (i = 0; i < restart->len; i++)
879 restart->pdata[i] = g_shell_quote (restart->pdata[i]);
880 g_ptr_array_add (restart, NULL((void*)0));
881 exec = g_strjoinv (" ", (char **)restart->pdata);
882 g_strfreev ((char **)restart->pdata);
883 g_ptr_array_free (restart, FALSE(0));
884
885 g_key_file_set_string (state_file, EGG_DESKTOP_FILE_GROUP"Desktop Entry",
886 EGG_DESKTOP_FILE_KEY_EXEC"Exec",
887 exec);
888 g_free (exec);
889 }
890 else
891 desktop_file = NULL((void*)0);
892
893 g_free (desktop_file_path);
894 }
895
896 /* Now write state_file to disk. (We can't use mktemp(), because
897 * that requires the filename to end with "XXXXXX", and we want
898 * it to end with ".desktop".)
899 */
900
901 data = g_key_file_to_data (state_file, NULL((void*)0), NULL((void*)0));
902 g_key_file_free (state_file);
903
904 offset = 0;
905 while (1)
906 {
907 state_file_path = g_strdup_printf ("%s%csession-state%c%s-%ld.%s",
908 g_get_user_config_dir (),
909 G_DIR_SEPARATOR'/', G_DIR_SEPARATOR'/',
910 g_get_prgname (),
911 (long)time (NULL((void*)0)) + offset,
912 desktop_file ? "desktop" : "state");
913
914 fd = open (state_file_path, O_WRONLY01 | O_CREAT0100 | O_EXCL0200, 0644);
915 if (fd == -1)
916 {
917 if (errno(*__errno_location ()) == EEXIST17)
918 {
919 offset++;
920 g_free (state_file_path);
921 continue;
922 }
923 else if (errno(*__errno_location ()) == ENOTDIR20 || errno(*__errno_location ()) == ENOENT2)
924 {
925 char *sep = strrchr (state_file_path, G_DIR_SEPARATOR'/');
926
927 *sep = '\0';
928 if (g_mkdir_with_parents (state_file_path, 0755) != 0)
929 {
930 g_warning ("Could not create directory '%s'",
931 state_file_path);
932 g_free (state_file_path);
933 state_file_path = NULL((void*)0);
934 break;
935 }
936
937 continue;
938 }
939
940 g_warning ("Could not create file '%s': %s",
941 state_file_path, g_strerror (errno(*__errno_location ())));
942 g_free (state_file_path);
943 state_file_path = NULL((void*)0);
944 break;
945 }
946
947 close (fd);
948 g_file_set_contents (state_file_path, data, -1, NULL((void*)0));
949 break;
950 }
951 g_free (data);
952
953 restart = generate_command (xsmp->restart_command, xsmp->client_id,
954 state_file_path);
955 set_properties (xsmp,
956 ptrarray_prop (SmRestartCommand"RestartCommand", restart),
957 NULL((void*)0));
958 g_ptr_array_free (restart, TRUE(!(0)));
959
960 if (state_file_path)
961 {
962 set_properties (xsmp,
963 array_prop (SmDiscardCommand"DiscardCommand",
964 "/bin/rm", "-rf", state_file_path,
965 NULL((void*)0)),
966 NULL((void*)0));
967 g_free (state_file_path);
968 }
969}
970
971static void
972xsmp_interact (SmcConn smc_conn,
973 SmPointer client_data)
974{
975 EggSMClientXSMP *xsmp = client_data;
976 EggSMClient *client = client_data;
977
978 g_debug ("Received Interact message in state %s",
979 EGG_SM_CLIENT_XSMP_STATE (xsmp)(state_names[(xsmp)->state]));
980
981 if (xsmp->state != XSMP_STATE_INTERACT_REQUEST)
982 {
983 fix_broken_state (xsmp, "Interact", TRUE(!(0)), TRUE(!(0)));
984 return;
985 }
986
987 xsmp->state = XSMP_STATE_INTERACT;
988 egg_sm_client_quit_requested (client);
989}
990
991static void
992xsmp_die (SmcConn smc_conn,
993 SmPointer client_data)
994{
995 EggSMClientXSMP *xsmp = client_data;
996 EggSMClient *client = client_data;
997
998 g_debug ("Received Die message in state %s",
999 EGG_SM_CLIENT_XSMP_STATE (xsmp)(state_names[(xsmp)->state]));
1000
1001 sm_client_xsmp_disconnect (xsmp);
1002 egg_sm_client_quit (client);
1003}
1004
1005static void
1006xsmp_save_complete (SmcConn smc_conn,
1007 SmPointer client_data)
1008{
1009 EggSMClientXSMP *xsmp = client_data;
1010
1011 g_debug ("Received SaveComplete message in state %s",
1012 EGG_SM_CLIENT_XSMP_STATE (xsmp)(state_names[(xsmp)->state]));
1013
1014 if (xsmp->state == XSMP_STATE_SAVE_YOURSELF_DONE)
1015 xsmp->state = XSMP_STATE_IDLE;
1016 else
1017 fix_broken_state (xsmp, "SaveComplete", FALSE(0), FALSE(0));
1018}
1019
1020static void
1021xsmp_shutdown_cancelled (SmcConn smc_conn,
1022 SmPointer client_data)
1023{
1024 EggSMClientXSMP *xsmp = client_data;
1025 EggSMClient *client = client_data;
1026
1027 g_debug ("Received ShutdownCancelled message in state %s",
1028 EGG_SM_CLIENT_XSMP_STATE (xsmp)(state_names[(xsmp)->state]));
1029
1030 xsmp->shutting_down = FALSE(0);
1031
1032 if (xsmp->state == XSMP_STATE_SAVE_YOURSELF_DONE)
1033 {
1034 /* We've finished interacting and now the SM has agreed to
1035 * cancel the shutdown.
1036 */
1037 xsmp->state = XSMP_STATE_IDLE;
1038 egg_sm_client_quit_cancelled (client);
1039 }
1040 else if (xsmp->state == XSMP_STATE_SHUTDOWN_CANCELLED)
1041 {
1042 /* Hm... ok, so we got a shutdown SaveYourself, which got
1043 * cancelled, but the application was still interacting, so we
1044 * didn't tell it yet, and then *another* SaveYourself arrived,
1045 * which we must still be waiting to tell the app about, except
1046 * that now that SaveYourself has been cancelled too! Dizzy yet?
1047 */
1048 xsmp->waiting_to_save_myself = FALSE(0);
1049 update_pending_events (xsmp);
1050 }
1051 else
1052 {
1053 g_debug ("Sending SaveYourselfDone(False)");
1054 SmcSaveYourselfDone (xsmp->connection, False0);
1055
1056 if (xsmp->state == XSMP_STATE_INTERACT)
1057 {
1058 /* The application is currently interacting, so we can't
1059 * tell it about the cancellation yet; we will wait until
1060 * after it calls egg_sm_client_will_quit().
1061 */
1062 xsmp->state = XSMP_STATE_SHUTDOWN_CANCELLED;
1063 }
1064 else
1065 {
1066 /* The shutdown was cancelled before the application got a
1067 * chance to interact.
1068 */
1069 xsmp->state = XSMP_STATE_IDLE;
1070 }
1071 }
1072}
1073
1074/* Utilities */
1075
1076/* Create a restart/clone/Exec command based on @restart_command.
1077 * If @client_id is non-%NULL, add "--sm-client-id @client_id".
1078 * If @state_file is non-%NULL, add "--sm-client-state-file @state_file".
1079 *
1080 * None of the input strings are g_strdup()ed; the caller must keep
1081 * them around until it is done with the returned GPtrArray, and must
1082 * then free the array, but not its contents.
1083 */
1084static GPtrArray *
1085generate_command (char **restart_command, const char *client_id,
1086 const char *state_file)
1087{
1088 GPtrArray *cmd;
1089 int i;
1090
1091 cmd = g_ptr_array_new ();
1092 g_ptr_array_add (cmd, restart_command[0]);
1093
1094 if (client_id)
1095 {
1096 g_ptr_array_add (cmd, (char *)"--sm-client-id");
1097 g_ptr_array_add (cmd, (char *)client_id);
1098 }
1099
1100 if (state_file)
1101 {
1102 g_ptr_array_add (cmd, (char *)"--sm-client-state-file");
1103 g_ptr_array_add (cmd, (char *)state_file);
1104 }
1105
1106 for (i = 1; restart_command[i]; i++)
1107 g_ptr_array_add (cmd, restart_command[i]);
1108
1109 return cmd;
1110}
1111
1112/* Takes a NULL-terminated list of SmProp * values, created by
1113 * array_prop, ptrarray_prop, string_prop, card8_prop, sets them, and
1114 * frees them.
1115 */
1116static void
1117set_properties (EggSMClientXSMP *xsmp, ...)
1118{
1119 GPtrArray *props;
1120 SmProp *prop;
1121 va_list ap;
1122 guint i;
1123
1124 props = g_ptr_array_new ();
1125
1126 va_start (ap, xsmp)__builtin_va_start(ap, xsmp);
1127 while ((prop = va_arg (ap, SmProp *)__builtin_va_arg(ap, SmProp *)))
1128 g_ptr_array_add (props, prop);
1129 va_end (ap)__builtin_va_end(ap);
1130
1131 if (xsmp->connection)
1132 {
1133 SmcSetProperties (xsmp->connection, props->len,
1134 (SmProp **)props->pdata);
1135 }
1136
1137 for (i = 0; i < props->len; i++)
1138 {
1139 prop = props->pdata[i];
1140 g_free (prop->vals);
1141 g_free (prop);
1142 }
1143 g_ptr_array_free (props, TRUE(!(0)));
1144}
1145
1146/* Takes a NULL-terminated list of property names and deletes them. */
1147static void
1148delete_properties (EggSMClientXSMP *xsmp, ...)
1149{
1150 GPtrArray *props;
1151 char *prop;
1152 va_list ap;
1153
1154 if (!xsmp->connection)
1155 return;
1156
1157 props = g_ptr_array_new ();
1158
1159 va_start (ap, xsmp)__builtin_va_start(ap, xsmp);
1160 while ((prop = va_arg (ap, char *)__builtin_va_arg(ap, char *)))
1161 g_ptr_array_add (props, prop);
1162 va_end (ap)__builtin_va_end(ap);
1163
1164 SmcDeleteProperties (xsmp->connection, props->len,
1165 (char **)props->pdata);
1166
1167 g_ptr_array_free (props, TRUE(!(0)));
1168}
1169
1170/* Takes an array of strings and creates a LISTofARRAY8 property. The
1171 * strings are neither dupped nor freed; they need to remain valid
1172 * until you're done with the SmProp.
1173 */
1174static SmProp *
1175array_prop (const char *name, ...)
1176{
1177 SmProp *prop;
1178 SmPropValue pv;
1179 GArray *vals;
1180 char *value;
1181 va_list ap;
1182
1183 prop = g_new (SmProp, 1)(SmProp *) (__extension__ ({ gsize __n = (gsize) (1); gsize __s
= sizeof (SmProp); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
1184 prop->name = (char *)name;
1185 prop->type = (char *)SmLISTofARRAY8"LISTofARRAY8";
1186
1187 vals = g_array_new (FALSE(0), FALSE(0), sizeof (SmPropValue));
1188
1189 va_start (ap, name)__builtin_va_start(ap, name);
1190 while ((value = va_arg (ap, char *)__builtin_va_arg(ap, char *)))
1191 {
1192 pv.length = strlen (value);
1193 pv.value = value;
1194 g_array_append_val (vals, pv)g_array_append_vals (vals, &(pv), 1);
1195 }
1196 va_end (ap)__builtin_va_end(ap);
1197
1198 prop->num_vals = vals->len;
1199 prop->vals = (SmPropValue *)vals->data;
1200
1201 g_array_free (vals, FALSE(0));
1202
1203 return prop;
1204}
1205
1206/* Takes a GPtrArray of strings and creates a LISTofARRAY8 property.
1207 * The array contents are neither dupped nor freed; they need to
1208 * remain valid until you're done with the SmProp.
1209 */
1210static SmProp *
1211ptrarray_prop (const char *name, GPtrArray *values)
1212{
1213 SmProp *prop;
1214 SmPropValue pv;
1215 GArray *vals;
1216 guint i;
1217
1218 prop = g_new (SmProp, 1)(SmProp *) (__extension__ ({ gsize __n = (gsize) (1); gsize __s
= sizeof (SmProp); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
1219 prop->name = (char *)name;
1220 prop->type = (char *)SmLISTofARRAY8"LISTofARRAY8";
1221
1222 vals = g_array_new (FALSE(0), FALSE(0), sizeof (SmPropValue));
1223
1224 for (i = 0; i < values->len; i++)
1225 {
1226 pv.length = strlen (values->pdata[i]);
1227 pv.value = values->pdata[i];
1228 g_array_append_val (vals, pv)g_array_append_vals (vals, &(pv), 1);
1229 }
1230
1231 prop->num_vals = vals->len;
1232 prop->vals = (SmPropValue *)vals->data;
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption
1233
1234 g_array_free (vals, FALSE(0));
1235
1236 return prop;
1237}
1238
1239/* Takes a string and creates an ARRAY8 property. The string is
1240 * neither dupped nor freed; it needs to remain valid until you're
1241 * done with the SmProp.
1242 */
1243static SmProp *
1244string_prop (const char *name, const char *value)
1245{
1246 SmProp *prop;
1247
1248 prop = g_new (SmProp, 1)(SmProp *) (__extension__ ({ gsize __n = (gsize) (1); gsize __s
= sizeof (SmProp); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
1249 prop->name = (char *)name;
1250 prop->type = (char *)SmARRAY8"ARRAY8";
1251
1252 prop->num_vals = 1;
1253 prop->vals = g_new (SmPropValue, 1)(SmPropValue *) (__extension__ ({ gsize __n = (gsize) (1); gsize
__s = sizeof (SmPropValue); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
1254
1255 prop->vals[0].length = strlen (value);
1256 prop->vals[0].value = (char *)value;
1257
1258 return prop;
1259}
1260
1261/* Takes a char and creates a CARD8 property. */
1262static SmProp *
1263card8_prop (const char *name, unsigned char value)
1264{
1265 SmProp *prop;
1266 char *card8val;
1267
1268 /* To avoid having to allocate and free prop->vals[0], we cheat and
1269 * make vals a 2-element-long array and then use the second element
1270 * to store value.
1271 */
1272
1273 prop = g_new (SmProp, 1)(SmProp *) (__extension__ ({ gsize __n = (gsize) (1); gsize __s
= sizeof (SmProp); gpointer __p; if (__s == 1) __p = g_malloc
(__n); else if (__builtin_constant_p (__n) && (__s ==
0 || __n <= (9223372036854775807L *2UL+1UL) / __s)) __p =
g_malloc (__n * __s); else __p = g_malloc_n (__n, __s); __p;
}))
;
1274 prop->name = (char *)name;
1275 prop->type = (char *)SmCARD8"CARD8";
1276
1277 prop->num_vals = 1;
1278 prop->vals = g_new (SmPropValue, 2)(SmPropValue *) (__extension__ ({ gsize __n = (gsize) (2); gsize
__s = sizeof (SmPropValue); gpointer __p; if (__s == 1) __p =
g_malloc (__n); else if (__builtin_constant_p (__n) &&
(__s == 0 || __n <= (9223372036854775807L *2UL+1UL) / __s
)) __p = g_malloc (__n * __s); else __p = g_malloc_n (__n, __s
); __p; }))
;
1279 card8val = (char *)(&prop->vals[1]);
1280 card8val[0] = value;
1281
1282 prop->vals[0].length = 1;
1283 prop->vals[0].value = card8val;
1284
1285 return prop;
1286}
1287
1288/* ICE code. This makes no effort to play nice with anyone else trying
1289 * to use libICE. Fortunately, no one uses libICE for anything other
1290 * than SM. (DCOP uses ICE, but it has its own private copy of
1291 * libICE.)
1292 *
1293 * When this moves to gtk, it will need to be cleverer, to avoid
1294 * tripping over old apps that use MateClient or that use libSM
1295 * directly.
1296 */
1297
1298#include <X11/ICE/ICElib.h>
1299#include <fcntl.h>
1300
1301static void ice_error_handler (IceConn ice_conn,
1302 Boolint swap,
1303 int offending_minor_opcode,
1304 unsigned long offending_sequence,
1305 int error_class,
1306 int severity,
1307 IcePointer values);
1308static void ice_io_error_handler (IceConn ice_conn);
1309static void ice_connection_watch (IceConn ice_conn,
1310 IcePointer client_data,
1311 Boolint opening,
1312 IcePointer *watch_data);
1313
1314static void
1315ice_init (void)
1316{
1317 IceSetIOErrorHandler (ice_io_error_handler);
1318 IceSetErrorHandler (ice_error_handler);
1319 IceAddConnectionWatch (ice_connection_watch, NULL((void*)0));
1320}
1321
1322static gboolean
1323process_ice_messages (IceConn ice_conn)
1324{
1325 IceProcessMessagesStatus status;
1326 status = IceProcessMessages (ice_conn, NULL((void*)0), NULL((void*)0));
1327
1328 switch (status)
1329 {
1330 case IceProcessMessagesSuccess:
1331 return TRUE(!(0));
1332
1333 case IceProcessMessagesIOError:
1334 sm_client_xsmp_disconnect (IceGetConnectionContext (ice_conn));
1335 return FALSE(0);
1336
1337 case IceProcessMessagesConnectionClosed:
1338 return FALSE(0);
1339
1340 default:
1341 g_assert_not_reached ()do { g_assertion_message_expr ("EggSMClient", "eggsmclient-xsmp.c"
, 1341, ((const char*) (__func__)), ((void*)0)); } while (0)
;
1342 }
1343}
1344
1345static gboolean
1346ice_iochannel_watch (GIOChannel *channel,
1347 GIOCondition condition,
1348 gpointer client_data)
1349{
1350 return process_ice_messages (client_data);
1351}
1352
1353static void
1354ice_connection_watch (IceConn ice_conn,
1355 IcePointer client_data,
1356 Boolint opening,
1357 IcePointer *watch_data)
1358{
1359 guint watch_id;
1360
1361 if (opening)
1362 {
1363 GIOChannel *channel;
1364 int fd = IceConnectionNumber (ice_conn);
1365
1366 fcntl (fd, F_SETFD2, fcntl (fd, F_GETFD1, 0) | FD_CLOEXEC1);
1367 channel = g_io_channel_unix_new (fd);
1368 watch_id = g_io_add_watch (channel, G_IO_IN | G_IO_ERR,
1369 ice_iochannel_watch, ice_conn);
1370 g_io_channel_unref (channel);
1371
1372 *watch_data = GUINT_TO_POINTER (watch_id)((gpointer) (gulong) (watch_id));
1373 }
1374 else
1375 {
1376 watch_id = GPOINTER_TO_UINT (*watch_data)((guint) (gulong) (*watch_data));
1377 g_source_remove (watch_id);
1378 }
1379}
1380
1381static void
1382ice_error_handler (IceConn ice_conn,
1383 Boolint swap,
1384 int offending_minor_opcode,
1385 unsigned long offending_sequence,
1386 int error_class,
1387 int severity,
1388 IcePointer values)
1389{
1390 /* Do nothing */
1391}
1392
1393static void
1394ice_io_error_handler (IceConn ice_conn)
1395{
1396 /* Do nothing */
1397}
1398
1399static void
1400smc_error_handler (SmcConn smc_conn,
1401 Boolint swap,
1402 int offending_minor_opcode,
1403 unsigned long offending_sequence,
1404 int error_class,
1405 int severity,
1406 SmPointer values)
1407{
1408 /* Do nothing */
1409}
diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-efdf48.html b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-efdf48.html new file mode 100644 index 00000000..5e5ecc4a --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-efdf48.html @@ -0,0 +1,1150 @@ + + + +bacon-message-connection.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:pluma/bacon-message-connection.c
Warning:line 169, column 30
Out of bound memory access (access exceeds upper limit of memory block)
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name bacon-message-connection.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/pluma -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I .. -I .. -I . -I ./mate-submodules/libegg -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/gtksourceview-4 -I /usr/include/libpeas-1.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -D DATADIR="/usr/local/share" -D PLUMA_DATADIR="/usr/local/share/pluma" -D PLUMA_LOCALEDIR="/usr/local/share/locale/" -D LIBDIR="/usr/local/lib" -D PLUMA_LIBDIR="/usr/local/lib/pluma" -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/pluma -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-10-22-114445-13211-1 -x c bacon-message-connection.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/*
2 * Copyright (C) 2003 Bastien Nocera <hadess@hadess.net>
3 * Copyright (C) 2012-2021 MATE Developers
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
19 */
20
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <stdio.h>
25#include <string.h>
26#include <unistd.h>
27#include <sys/types.h>
28#include <sys/socket.h>
29#include <sys/un.h>
30#include <errno(*__errno_location ()).h>
31
32#include "bacon-message-connection.h"
33
34#ifndef UNIX_PATH_MAX108
35#define UNIX_PATH_MAX108 108
36#endif
37
38struct BaconMessageConnection {
39 /* A server accepts connections */
40 gboolean is_server;
41
42 /* The socket path itself */
43 char *path;
44
45 /* File descriptor of the socket */
46 int fd;
47 /* Channel to watch */
48 GIOChannel *chan;
49 /* Event id returned by g_io_add_watch() */
50 int conn_id;
51
52 /* Connections accepted by this connection */
53 GSList *accepted_connections;
54
55 /* callback */
56 void (*func) (const char *message, gpointer user_data);
57 gpointer data;
58};
59
60static gboolean
61test_is_socket (const char *path)
62{
63 struct stat s;
64
65 if (stat (path, &s) == -1)
66 return FALSE(0);
67
68 if (S_ISSOCK (s.st_mode)((((s.st_mode)) & 0170000) == (0140000)))
69 return TRUE(!(0));
70
71 return FALSE(0);
72}
73
74static gboolean
75is_owned_by_user_and_socket (const char *path)
76{
77 struct stat s;
78
79 if (stat (path, &s) == -1)
80 return FALSE(0);
81
82 if (s.st_uid != geteuid ())
83 return FALSE(0);
84
85 if ((s.st_mode & S_IFSOCK0140000) != S_IFSOCK0140000)
86 return FALSE(0);
87
88 return TRUE(!(0));
89}
90
91static gboolean server_cb (GIOChannel *source,
92 GIOCondition condition, gpointer data);
93
94static gboolean
95setup_connection (BaconMessageConnection *conn)
96{
97 g_return_val_if_fail (conn->chan == NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_17
; if (conn->chan == ((void*)0)) _g_boolean_var_17 = 1; else
_g_boolean_var_17 = 0; _g_boolean_var_17; }), 1))) { } else {
g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__
)), "conn->chan == NULL"); return ((0)); } } while (0)
;
98
99 conn->chan = g_io_channel_unix_new (conn->fd);
100 if (!conn->chan) {
101 return FALSE(0);
102 }
103 g_io_channel_set_line_term (conn->chan, "\n", 1);
104 conn->conn_id = g_io_add_watch (conn->chan, G_IO_IN, server_cb, conn);
105
106 return TRUE(!(0));
107}
108
109static void
110accept_new_connection (BaconMessageConnection *server_conn)
111{
112 BaconMessageConnection *conn;
113 int alen;
114
115 g_return_if_fail (server_conn->is_server)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_18
; if (server_conn->is_server) _g_boolean_var_18 = 1; else _g_boolean_var_18
= 0; _g_boolean_var_18; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "server_conn->is_server"
); return; } } while (0)
;
116
117 conn = g_new0 (BaconMessageConnection, 1)(BaconMessageConnection *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (BaconMessageConnection); gpointer __p
; if (__s == 1) __p = g_malloc0 (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n
(__n, __s); __p; }))
;
118 conn->is_server = FALSE(0);
119 conn->func = server_conn->func;
120 conn->data = server_conn->data;
121
122 conn->fd = accept (server_conn->fd, NULL((void*)0), (guint *)&alen);
123
124 server_conn->accepted_connections =
125 g_slist_prepend (server_conn->accepted_connections, conn);
126
127 setup_connection (conn);
128}
129
130static gboolean
131server_cb (GIOChannel *source, GIOCondition condition, gpointer data)
132{
133 BaconMessageConnection *conn = (BaconMessageConnection *)data;
134 char *message, *subs, buf;
135 int cd, rc, offset;
136 gboolean finished;
137
138 offset = 0;
139 if (conn->is_server && conn->fd == g_io_channel_unix_get_fd (source)) {
1
Assuming field 'is_server' is 0
140 accept_new_connection (conn);
141 return TRUE(!(0));
142 }
143 message = g_malloc (1);
144 cd = conn->fd;
145 rc = read (cd, &buf, 1);
146 while (rc > 0 && buf != '\n')
2
Assuming 'rc' is > 0
3
Assuming the condition is true
4
Loop condition is true. Entering loop body
5
Assuming 'rc' is > 0
6
Assuming the condition is true
7
Loop condition is true. Entering loop body
8
Assuming 'rc' is > 0
9
Assuming the condition is false
10
Loop condition is false. Execution continues on line 153
147 {
148 message = g_realloc (message, rc + offset + 1);
149 message[offset] = buf;
150 offset = offset + rc;
151 rc = read (cd, &buf, 1);
152 }
153 if (rc
10.1
'rc' is > 0
<= 0) {
11
Taking false branch
154 g_io_channel_shutdown (conn->chan, FALSE(0), NULL((void*)0));
155 g_io_channel_unref (conn->chan);
156 conn->chan = NULL((void*)0);
157 close (conn->fd);
158 conn->fd = -1;
159 g_free (message);
160 conn->conn_id = 0;
161
162 return FALSE(0);
163 }
164 message[offset] = '\0';
165
166 subs = message;
167 finished = FALSE(0);
168
169 while (finished
11.1
'finished' is equal to FALSE
16.1
'finished' is equal to FALSE
20.1
'finished' is equal to FALSE
== FALSE(0) && *subs != '\0')
12
Loop condition is true. Entering loop body
16
Taking false branch
17
Loop condition is true. Entering loop body
20
Taking false branch
21
Out of bound memory access (access exceeds upper limit of memory block)
170 {
171 if (conn->func
17.1
Field 'func' is equal to NULL
!= NULL((void*)0)
)
13
Assuming field 'func' is equal to NULL
14
Taking false branch
18
Taking false branch
172 (*conn->func) (subs, conn->data);
173
174 subs += strlen (subs) + 1;
175 if (subs - message >= offset)
15
Assuming the condition is false
19
Assuming the condition is false
176 finished = TRUE(!(0));
177 }
178
179 g_free (message);
180
181 return TRUE(!(0));
182}
183
184static char *
185find_file_with_pattern (const char *dir, const char *pattern)
186{
187 GDir *filedir;
188 char *found_filename;
189 const char *filename;
190 GPatternSpec *pat;
191
192 filedir = g_dir_open (dir, 0, NULL((void*)0));
193 if (filedir == NULL((void*)0))
194 return NULL((void*)0);
195
196 pat = g_pattern_spec_new (pattern);
197 if (pat == NULL((void*)0))
198 {
199 g_dir_close (filedir);
200 return NULL((void*)0);
201 }
202
203 found_filename = NULL((void*)0);
204
205 while ((filename = g_dir_read_name (filedir)))
206 {
207 if (g_pattern_match_string (pat, filename))
208 {
209 char *tmp = g_build_filename (dir, filename, NULL((void*)0));
210 if (is_owned_by_user_and_socket (tmp))
211 found_filename = g_strdup (filename)g_strdup_inline (filename);
212 g_free (tmp);
213 }
214
215 if (found_filename != NULL((void*)0))
216 break;
217 }
218
219 g_pattern_spec_free (pat);
220 g_dir_close (filedir);
221
222 return found_filename;
223}
224
225static char *
226socket_filename (const char *prefix)
227{
228 char *pattern, *newfile, *path, *filename;
229 const char *tmpdir;
230
231 pattern = g_strdup_printf ("%s.%s.*", prefix, g_get_user_name ());
232 tmpdir = g_get_tmp_dir ();
233 filename = find_file_with_pattern (tmpdir, pattern);
234 if (filename == NULL((void*)0))
235 {
236 newfile = g_strdup_printf ("%s.%s.%u", prefix,
237 g_get_user_name (), g_random_int ());
238 path = g_build_filename (tmpdir, newfile, NULL((void*)0));
239 g_free (newfile);
240 } else {
241 path = g_build_filename (tmpdir, filename, NULL((void*)0));
242 g_free (filename);
243 }
244
245 g_free (pattern);
246 return path;
247}
248
249static gboolean
250try_server (BaconMessageConnection *conn)
251{
252 struct sockaddr_un uaddr;
253
254 uaddr.sun_family = AF_UNIX1;
255 strncpy (uaddr.sun_path, conn->path,
256 MIN (strlen(conn->path)+1, UNIX_PATH_MAX)(((strlen(conn->path)+1) < (108)) ? (strlen(conn->path
)+1) : (108))
);
257 conn->fd = socket (PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0);
258 if (bind (conn->fd, (struct sockaddr *) &uaddr, sizeof (uaddr)) == -1)
259 {
260 conn->fd = -1;
261 return FALSE(0);
262 }
263 listen (conn->fd, 5);
264
265 if (!setup_connection (conn))
266 return FALSE(0);
267 return TRUE(!(0));
268}
269
270static gboolean
271try_client (BaconMessageConnection *conn)
272{
273 struct sockaddr_un uaddr;
274
275 uaddr.sun_family = AF_UNIX1;
276 strncpy (uaddr.sun_path, conn->path,
277 MIN(strlen(conn->path)+1, UNIX_PATH_MAX)(((strlen(conn->path)+1) < (108)) ? (strlen(conn->path
)+1) : (108))
);
278 conn->fd = socket (PF_UNIX1, SOCK_STREAMSOCK_STREAM, 0);
279 if (connect (conn->fd, (struct sockaddr *) &uaddr,
280 sizeof (uaddr)) == -1)
281 {
282 conn->fd = -1;
283 return FALSE(0);
284 }
285
286 return setup_connection (conn);
287}
288
289BaconMessageConnection *
290bacon_message_connection_new (const char *prefix)
291{
292 BaconMessageConnection *conn;
293
294 g_return_val_if_fail (prefix != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_19
; if (prefix != ((void*)0)) _g_boolean_var_19 = 1; else _g_boolean_var_19
= 0; _g_boolean_var_19; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "prefix != NULL")
; return (((void*)0)); } } while (0)
;
295
296 conn = g_new0 (BaconMessageConnection, 1)(BaconMessageConnection *) (__extension__ ({ gsize __n = (gsize
) (1); gsize __s = sizeof (BaconMessageConnection); gpointer __p
; if (__s == 1) __p = g_malloc0 (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc0 (__n * __s); else __p = g_malloc0_n
(__n, __s); __p; }))
;
297 conn->path = socket_filename (prefix);
298
299 if (test_is_socket (conn->path) == FALSE(0))
300 {
301 if (!try_server (conn))
302 {
303 bacon_message_connection_free (conn);
304 return NULL((void*)0);
305 }
306
307 conn->is_server = TRUE(!(0));
308 return conn;
309 }
310
311 if (try_client (conn) == FALSE(0))
312 {
313 unlink (conn->path);
314 try_server (conn);
315 if (conn->fd == -1)
316 {
317 bacon_message_connection_free (conn);
318 return NULL((void*)0);
319 }
320
321 conn->is_server = TRUE(!(0));
322 return conn;
323 }
324
325 conn->is_server = FALSE(0);
326 return conn;
327}
328
329void
330bacon_message_connection_free (BaconMessageConnection *conn)
331{
332 GSList *child_conn;
333
334 g_return_if_fail (conn != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_20
; if (conn != ((void*)0)) _g_boolean_var_20 = 1; else _g_boolean_var_20
= 0; _g_boolean_var_20; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "conn != NULL"); return
; } } while (0)
;
335 /* Only servers can accept other connections */
336 g_return_if_fail (conn->is_server != FALSE ||do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_21
; if (conn->is_server != (0) || conn->accepted_connections
== ((void*)0)) _g_boolean_var_21 = 1; else _g_boolean_var_21
= 0; _g_boolean_var_21; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "conn->is_server != FALSE || conn->accepted_connections == NULL"
); return; } } while (0)
337 conn->accepted_connections == NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_21
; if (conn->is_server != (0) || conn->accepted_connections
== ((void*)0)) _g_boolean_var_21 = 1; else _g_boolean_var_21
= 0; _g_boolean_var_21; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "conn->is_server != FALSE || conn->accepted_connections == NULL"
); return; } } while (0)
;
338
339 child_conn = conn->accepted_connections;
340 while (child_conn != NULL((void*)0)) {
341 bacon_message_connection_free (child_conn->data);
342 child_conn = g_slist_next (child_conn)((child_conn) ? (((GSList *)(child_conn))->next) : ((void*
)0))
;
343 }
344 g_slist_free (conn->accepted_connections);
345
346 if (conn->conn_id) {
347 g_source_remove (conn->conn_id);
348 conn->conn_id = 0;
349 }
350 if (conn->chan) {
351 g_io_channel_shutdown (conn->chan, FALSE(0), NULL((void*)0));
352 g_io_channel_unref (conn->chan);
353 }
354
355 if (conn->is_server != FALSE(0)) {
356 unlink (conn->path);
357 }
358 if (conn->fd != -1) {
359 close (conn->fd);
360 }
361
362 g_free (conn->path);
363 g_free (conn);
364}
365
366void
367bacon_message_connection_set_callback (BaconMessageConnection *conn,
368 BaconMessageReceivedFunc func,
369 gpointer user_data)
370{
371 g_return_if_fail (conn != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_22
; if (conn != ((void*)0)) _g_boolean_var_22 = 1; else _g_boolean_var_22
= 0; _g_boolean_var_22; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "conn != NULL"); return
; } } while (0)
;
372
373 conn->func = func;
374 conn->data = user_data;
375}
376
377void
378bacon_message_connection_send (BaconMessageConnection *conn,
379 const char *message)
380{
381 g_return_if_fail (conn != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_23
; if (conn != ((void*)0)) _g_boolean_var_23 = 1; else _g_boolean_var_23
= 0; _g_boolean_var_23; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "conn != NULL"); return
; } } while (0)
;
382 g_return_if_fail (message != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_24
; if (message != ((void*)0)) _g_boolean_var_24 = 1; else _g_boolean_var_24
= 0; _g_boolean_var_24; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "message != NULL"
); return; } } while (0)
;
383
384 g_io_channel_write_chars (conn->chan, message, strlen (message),
385 NULL((void*)0), NULL((void*)0));
386 g_io_channel_write_chars (conn->chan, "\n", 1, NULL((void*)0), NULL((void*)0));
387 g_io_channel_flush (conn->chan, NULL((void*)0));
388}
389
390gboolean
391bacon_message_connection_get_is_server (BaconMessageConnection *conn)
392{
393 g_return_val_if_fail (conn != NULL, FALSE)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_25
; if (conn != ((void*)0)) _g_boolean_var_25 = 1; else _g_boolean_var_25
= 0; _g_boolean_var_25; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "conn != NULL"); return
((0)); } } while (0)
;
394
395 return conn->is_server;
396}
397
diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-f2c91f.html b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-f2c91f.html new file mode 100644 index 00000000..19799e77 --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/report-f2c91f.html @@ -0,0 +1,1120 @@ + + + +pluma-spell-checker-language.c + + + + + + + + + + + + + + + + + + + + + + + + + + +

Bug Summary

+ + + + +
File:plugins/spell/pluma-spell-checker-language.c
Warning:line 195, column 8
true and false branches are identical
+ +

Annotated Source Code

+

Press '?' + to see keyboard shortcuts

+ + +
clang -cc1 -cc1 -triple x86_64-redhat-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name pluma-spell-checker-language.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/plugins/spell -resource-dir /usr/lib64/clang/16 -D HAVE_CONFIG_H -I . -I ../.. -I ../.. -I /usr/include/libxml2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/gtksourceview-4 -I /usr/include/libpeas-1.0 -I /usr/include/gobject-introspection-1.0 -I /usr/include/enchant-2 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/mate-desktop-2.0 -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib64/glib-2.0/include -I /usr/include/sysprof-4 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/libxml2 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib64/dbus-1.0/include -I /usr/include/dconf -D PIC -internal-isystem /usr/lib64/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/13/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -fdebug-compilation-dir=/rootdir/plugins/spell -ferror-limit 19 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-checker security.insecureAPI.strcpy -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-10-22-114445-13211-1 -x c pluma-spell-checker-language.c +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*
3 * pluma-spell-checker-language.c
4 * This file is part of pluma
5 *
6 * Copyright (C) 2006 Paolo Maggi
7 * Copyright (C) 2012-2021 MATE Developers
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 */
24
25/*
26 * Modified by the pluma Team, 2006. See the AUTHORS file for a
27 * list of people on the pluma Team.
28 * See the ChangeLog files for a list of changes.
29 */
30
31/* Part of the code taked from Epiphany.
32 *
33 * Copyright (C) 2003, 2004 Christian Persch
34 */
35
36#ifdef HAVE_CONFIG_H1
37#include <config.h>
38#endif
39
40#include <string.h>
41
42#include <enchant.h>
43
44#include <glib/gi18n.h>
45#include <libxml/xmlreader.h>
46
47#include "pluma-spell-checker-language.h"
48
49#include <pluma/pluma-debug.h>
50
51#define ISO_639_DOMAIN"iso_639" "iso_639"
52#define ISO_3166_DOMAIN"iso_3166" "iso_3166"
53
54#define ISOCODESLOCALEDIR"/usr" "/share/locale" ISO_CODES_PREFIX"/usr" "/share/locale"
55
56struct _PlumaSpellCheckerLanguage
57{
58 gchar *abrev;
59 gchar *name;
60};
61
62static gboolean available_languages_initialized = FALSE(0);
63static GSList *available_languages = NULL((void*)0);
64
65static GHashTable *iso_639_table = NULL((void*)0);
66static GHashTable *iso_3166_table = NULL((void*)0);
67
68static void
69bind_iso_domains (void)
70{
71 static gboolean bound = FALSE(0);
72
73 if (bound == FALSE(0))
74 {
75 bindtextdomain (ISO_639_DOMAIN"iso_639", ISOCODESLOCALEDIR"/usr" "/share/locale");
76 bind_textdomain_codeset (ISO_639_DOMAIN"iso_639", "UTF-8");
77
78 bindtextdomain(ISO_3166_DOMAIN"iso_3166", ISOCODESLOCALEDIR"/usr" "/share/locale");
79 bind_textdomain_codeset (ISO_3166_DOMAIN"iso_3166", "UTF-8");
80
81 bound = TRUE(!(0));
82 }
83}
84
85static void
86read_iso_639_entry (xmlTextReaderPtr reader,
87 GHashTable *table)
88{
89 xmlChar *code, *name;
90
91 code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "iso_639_1_code");
92 name = xmlTextReaderGetAttribute (reader, (const xmlChar *) "name");
93
94 /* Get iso-639-2 code */
95 if (code == NULL((void*)0) || code[0] == '\0')
96 {
97 xmlFree (code);
98 /* FIXME: use the 2T or 2B code? */
99 code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "iso_639_2T_code");
100 }
101
102 if (code != NULL((void*)0) && code[0] != '\0' && name != NULL((void*)0) && name[0] != '\0')
103 {
104 g_hash_table_insert (table, code, name);
105 }
106 else
107 {
108 xmlFree (code);
109 xmlFree (name);
110 }
111}
112
113static void
114read_iso_3166_entry (xmlTextReaderPtr reader,
115 GHashTable *table)
116{
117 xmlChar *code, *name;
118
119 code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "alpha_2_code");
120 name = xmlTextReaderGetAttribute (reader, (const xmlChar *) "name");
121
122 if (code != NULL((void*)0) && code[0] != '\0' && name != NULL((void*)0) && name[0] != '\0')
123 {
124 char *lcode;
125
126 lcode = g_ascii_strdown ((char *) code, -1);
127 xmlFree (code);
128
129 /* g_print ("%s -> %s\n", lcode, name); */
130
131 g_hash_table_insert (table, lcode, name);
132 }
133 else
134 {
135 xmlFree (code);
136 xmlFree (name);
137 }
138}
139
140typedef enum
141{
142 STATE_START,
143 STATE_STOP,
144 STATE_ENTRIES,
145} ParserState;
146
147static void
148load_iso_entries (int iso,
149 GFunc read_entry_func,
150 gpointer user_data)
151{
152 xmlTextReaderPtr reader;
153 ParserState state = STATE_START;
154 xmlChar iso_entries[32], iso_entry[32];
155 char *filename;
156 int ret = -1;
157
158 pluma_debug_message (DEBUG_PLUGINSPLUMA_DEBUG_PLUGINS, "pluma-spell-checker-language.c", 158, (
(const char*) (__func__))
, "Loading ISO-%d codes", iso);
159
160 filename = g_strdup_printf (ISO_CODES_PREFIX"/usr" "/share/xml/iso-codes/iso_%d.xml", iso);
161 reader = xmlNewTextReaderFilename (filename);
162 if (reader == NULL((void*)0)) goto out;
163
164 xmlStrPrintf (iso_entries, sizeof (iso_entries), (const char *)"iso_%d_entries", iso);
165 xmlStrPrintf (iso_entry, sizeof (iso_entry), (const char *)"iso_%d_entry", iso);
166
167 ret = xmlTextReaderRead (reader);
168
169 while (ret == 1)
170 {
171 const xmlChar *tag;
172 xmlReaderTypes type;
173
174 tag = xmlTextReaderConstName (reader);
175 type = xmlTextReaderNodeType (reader);
176
177 if (state == STATE_ENTRIES &&
178 type == XML_READER_TYPE_ELEMENT &&
179 xmlStrEqual (tag, iso_entry))
180 {
181 read_entry_func (reader, user_data);
182 }
183 else if (state == STATE_START &&
184 type == XML_READER_TYPE_ELEMENT &&
185 xmlStrEqual (tag, iso_entries))
186 {
187 state = STATE_ENTRIES;
188 }
189 else if (state == STATE_ENTRIES &&
190 type == XML_READER_TYPE_END_ELEMENT &&
191 xmlStrEqual (tag, iso_entries))
192 {
193 state = STATE_STOP;
194 }
195 else if (type == XML_READER_TYPE_SIGNIFICANT_WHITESPACE ||
true and false branches are identical
196 type == XML_READER_TYPE_WHITESPACE ||
197 type == XML_READER_TYPE_TEXT ||
198 type == XML_READER_TYPE_COMMENT)
199 {
200 /* eat it */
201 }
202 else
203 {
204 /* ignore it */
205 }
206
207 ret = xmlTextReaderRead (reader);
208 }
209
210 xmlFreeTextReader (reader);
211
212out:
213 if (ret < 0 || state != STATE_STOP)
214 {
215 g_warning ("Failed to load ISO-%d codes from %s!\n",
216 iso, filename);
217 }
218
219 g_free (filename);
220}
221
222static GHashTable *
223create_iso_639_table (void)
224{
225 GHashTable *table;
226
227 bind_iso_domains ();
228 table = g_hash_table_new_full (g_str_hash, g_str_equal,
229 (GDestroyNotify) xmlFree,
230 (GDestroyNotify) xmlFree);
231
232 load_iso_entries (639, (GFunc) read_iso_639_entry, table);
233
234 return table;
235}
236
237static GHashTable *
238create_iso_3166_table (void)
239{
240 GHashTable *table;
241
242 bind_iso_domains ();
243 table = g_hash_table_new_full (g_str_hash, g_str_equal,
244 (GDestroyNotify) g_free,
245 (GDestroyNotify) xmlFree);
246
247 load_iso_entries (3166, (GFunc) read_iso_3166_entry, table);
248
249 return table;
250}
251
252static char *
253create_name_for_language (const char *code)
254{
255 char **str;
256 char *name = NULL((void*)0);
257 const char *langname, *localename;
258 int len;
259
260 g_return_val_if_fail (iso_639_table != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_16
; if (iso_639_table != ((void*)0)) _g_boolean_var_16 = 1; else
_g_boolean_var_16 = 0; _g_boolean_var_16; }), 1))) { } else {
g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__
)), "iso_639_table != NULL"); return (((void*)0)); } } while (
0)
;
261 g_return_val_if_fail (iso_3166_table != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_17
; if (iso_3166_table != ((void*)0)) _g_boolean_var_17 = 1; else
_g_boolean_var_17 = 0; _g_boolean_var_17; }), 1))) { } else {
g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__
)), "iso_3166_table != NULL"); return (((void*)0)); } } while
(0)
;
262
263 str = g_strsplit (code, "_", -1);
264 len = g_strv_length (str);
265 g_return_val_if_fail (len != 0, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_18
; if (len != 0) _g_boolean_var_18 = 1; else _g_boolean_var_18
= 0; _g_boolean_var_18; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "len != 0"); return
(((void*)0)); } } while (0)
;
266
267 langname = (const char *) g_hash_table_lookup (iso_639_table, str[0]);
268
269 if (len == 1 && langname != NULL((void*)0))
270 {
271 name = g_strdup (dgettext (ISO_639_DOMAIN, langname))g_strdup_inline (dcgettext ("iso_639", langname, 5));
272 }
273 else if (len == 2 && langname != NULL((void*)0))
274 {
275 gchar *locale_code = g_ascii_strdown (str[1], -1);
276
277 localename = (const char *) g_hash_table_lookup (iso_3166_table, locale_code);
278 g_free (locale_code);
279
280 if (localename != NULL((void*)0))
281 {
282 /* Translators: the first %s is the language name, and
283 * the second %s is the locale name. Example:
284 * "French (France)"
285 */
286 name = g_strdup_printf (C_("language", "%s (%s)")g_dpgettext (((void*)0), "language" "\004" "%s (%s)", strlen (
"language") + 1)
,
287 dgettext (ISO_639_DOMAIN, langname)dcgettext ("iso_639", langname, 5),
288 dgettext (ISO_3166_DOMAIN, localename)dcgettext ("iso_3166", localename, 5));
289 }
290 else
291 {
292 name = g_strdup_printf (C_("language", "%s (%s)")g_dpgettext (((void*)0), "language" "\004" "%s (%s)", strlen (
"language") + 1)
,
293 dgettext (ISO_639_DOMAIN, langname)dcgettext ("iso_639", langname, 5), str[1]);
294 }
295 }
296 else
297 {
298 /* Translators: this refers to an unknown language code
299 * (one which isn't in our built-in list).
300 */
301 name = g_strdup_printf (C_("language", "Unknown (%s)")g_dpgettext (((void*)0), "language" "\004" "Unknown (%s)", strlen
("language") + 1)
, code);
302 }
303
304 g_strfreev (str);
305
306 return name;
307}
308
309static void
310enumerate_dicts (const char * const lang_tag,
311 const char * const provider_name,
312 const char * const provider_desc,
313 const char * const provider_file,
314 void * user_data)
315{
316 gchar *lang_name;
317
318 GTree *dicts = (GTree *)user_data;
319
320 lang_name = create_name_for_language (lang_tag);
321 g_return_if_fail (lang_name != NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_19
; if (lang_name != ((void*)0)) _g_boolean_var_19 = 1; else _g_boolean_var_19
= 0; _g_boolean_var_19; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "lang_name != NULL"
); return; } } while (0)
;
322
323 /* g_print ("%s - %s\n", lang_tag, lang_name); */
324
325 g_tree_replace (dicts, g_strdup (lang_tag)g_strdup_inline (lang_tag), lang_name);
326}
327
328static gint
329key_cmp (gconstpointer a, gconstpointer b, gpointer user_data)
330{
331 return strcmp (a, b);
332}
333
334static gint
335lang_cmp (const PlumaSpellCheckerLanguage *a,
336 const PlumaSpellCheckerLanguage *b)
337{
338 return g_utf8_collate (a->name, b->name);
339}
340
341static gboolean
342build_langs_list (const gchar *key,
343 const gchar *value,
344 gpointer data)
345{
346 PlumaSpellCheckerLanguage *lang = g_new (PlumaSpellCheckerLanguage, 1)(PlumaSpellCheckerLanguage *) (__extension__ ({ gsize __n = (
gsize) (1); gsize __s = sizeof (PlumaSpellCheckerLanguage); gpointer
__p; if (__s == 1) __p = g_malloc (__n); else if (__builtin_constant_p
(__n) && (__s == 0 || __n <= (9223372036854775807L
*2UL+1UL) / __s)) __p = g_malloc (__n * __s); else __p = g_malloc_n
(__n, __s); __p; }))
;
347
348 lang->abrev = g_strdup (key)g_strdup_inline (key);
349 lang->name = g_strdup (value)g_strdup_inline (value);
350
351 available_languages = g_slist_insert_sorted (available_languages,
352 lang,
353 (GCompareFunc)lang_cmp);
354
355 return FALSE(0);
356}
357
358const GSList *
359pluma_spell_checker_get_available_languages (void)
360{
361 EnchantBroker *broker;
362 GTree *dicts;
363
364 if (available_languages_initialized)
365 return available_languages;
366
367 g_return_val_if_fail (available_languages == NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_20
; if (available_languages == ((void*)0)) _g_boolean_var_20 = 1
; else _g_boolean_var_20 = 0; _g_boolean_var_20; }), 1))) { }
else { g_return_if_fail_warning (((gchar*) 0), ((const char*
) (__func__)), "available_languages == NULL"); return (((void
*)0)); } } while (0)
;
368
369 available_languages_initialized = TRUE(!(0));
370
371 broker = enchant_broker_init ();
372 g_return_val_if_fail (broker != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_21
; if (broker != ((void*)0)) _g_boolean_var_21 = 1; else _g_boolean_var_21
= 0; _g_boolean_var_21; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "broker != NULL")
; return (((void*)0)); } } while (0)
;
373
374 /* Use a GTree to efficiently remove duplicates while building the list */
375 dicts = g_tree_new_full (key_cmp,
376 NULL((void*)0),
377 (GDestroyNotify)g_free,
378 (GDestroyNotify)g_free);
379
380 iso_639_table = create_iso_639_table ();
381 iso_3166_table = create_iso_3166_table ();
382
383 enchant_broker_list_dicts (broker, enumerate_dicts, dicts);
384
385 enchant_broker_free (broker);
386
387 g_hash_table_destroy (iso_639_table);
388 g_hash_table_destroy (iso_3166_table);
389
390 iso_639_table = NULL((void*)0);
391 iso_3166_table = NULL((void*)0);
392
393 g_tree_foreach (dicts, (GTraverseFunc)build_langs_list, NULL((void*)0));
394
395 g_tree_destroy (dicts);
396
397 return available_languages;
398}
399
400const gchar *
401pluma_spell_checker_language_to_string (const PlumaSpellCheckerLanguage *lang)
402{
403 if (lang == NULL((void*)0))
404 /* Translators: this refers the Default language used by the
405 * spell checker
406 */
407 return C_("language", "Default")g_dpgettext (((void*)0), "language" "\004" "Default", strlen (
"language") + 1)
;
408
409 return lang->name;
410}
411
412const gchar *
413pluma_spell_checker_language_to_key (const PlumaSpellCheckerLanguage *lang)
414{
415 g_return_val_if_fail (lang != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_22
; if (lang != ((void*)0)) _g_boolean_var_22 = 1; else _g_boolean_var_22
= 0; _g_boolean_var_22; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "lang != NULL"); return
(((void*)0)); } } while (0)
;
416
417 return lang->abrev;
418}
419
420const PlumaSpellCheckerLanguage *
421pluma_spell_checker_language_from_key (const gchar *key)
422{
423 const GSList *langs;
424
425 g_return_val_if_fail (key != NULL, NULL)do { if ((__builtin_expect (__extension__ ({ int _g_boolean_var_23
; if (key != ((void*)0)) _g_boolean_var_23 = 1; else _g_boolean_var_23
= 0; _g_boolean_var_23; }), 1))) { } else { g_return_if_fail_warning
(((gchar*) 0), ((const char*) (__func__)), "key != NULL"); return
(((void*)0)); } } while (0)
;
426
427 langs = pluma_spell_checker_get_available_languages ();
428
429 while (langs != NULL((void*)0))
430 {
431 const PlumaSpellCheckerLanguage *l = (const PlumaSpellCheckerLanguage *)langs->data;
432
433 if (g_ascii_strcasecmp (key, l->abrev) == 0)
434 return l;
435
436 langs = g_slist_next (langs)((langs) ? (((GSList *)(langs))->next) : ((void*)0));
437 }
438
439 return NULL((void*)0);
440}
diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/scanview.css b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/scanview.css new file mode 100644 index 00000000..cf8a5a6a --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/scanview.css @@ -0,0 +1,62 @@ +body { color:#000000; background-color:#ffffff } +body { font-family: Helvetica, sans-serif; font-size:9pt } +h1 { font-size: 14pt; } +h2 { font-size: 12pt; } +table { font-size:9pt } +table { border-spacing: 0px; border: 1px solid black } +th, table thead { + background-color:#eee; color:#666666; + font-weight: bold; cursor: default; + text-align:center; + font-weight: bold; font-family: Verdana; + white-space:nowrap; +} +.W { font-size:0px } +th, td { padding:5px; padding-left:8px; text-align:left } +td.SUMM_DESC { padding-left:12px } +td.DESC { white-space:pre } +td.Q { text-align:right } +td { text-align:left } +tbody.scrollContent { overflow:auto } + +table.form_group { + background-color: #ccc; + border: 1px solid #333; + padding: 2px; +} + +table.form_inner_group { + background-color: #ccc; + border: 1px solid #333; + padding: 0px; +} + +table.form { + background-color: #999; + border: 1px solid #333; + padding: 2px; +} + +td.form_label { + text-align: right; + vertical-align: top; +} +/* For one line entires */ +td.form_clabel { + text-align: right; + vertical-align: center; +} +td.form_value { + text-align: left; + vertical-align: top; +} +td.form_submit { + text-align: right; + vertical-align: top; +} + +h1.SubmitFail { + color: #f00; +} +h1.SubmitOk { +} diff --git a/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/sorttable.js b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/sorttable.js new file mode 100644 index 00000000..32faa078 --- /dev/null +++ b/2023-10-22-114445-13211-1@c884182e53c8_gtk-image-menu-item/sorttable.js @@ -0,0 +1,492 @@ +/* + SortTable + version 2 + 7th April 2007 + Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/ + + Instructions: + Download this file + Add to your HTML + Add class="sortable" to any table you'd like to make sortable + Click on the headers to sort + + Thanks to many, many people for contributions and suggestions. + Licenced as X11: http://www.kryogenix.org/code/browser/licence.html + This basically means: do what you want with it. +*/ + + +var stIsIE = /*@cc_on!@*/false; + +sorttable = { + init: function() { + // quit if this function has already been called + if (arguments.callee.done) return; + // flag this function so we don't do the same thing twice + arguments.callee.done = true; + // kill the timer + if (_timer) clearInterval(_timer); + + if (!document.createElement || !document.getElementsByTagName) return; + + sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; + + forEach(document.getElementsByTagName('table'), function(table) { + if (table.className.search(/\bsortable\b/) != -1) { + sorttable.makeSortable(table); + } + }); + + }, + + makeSortable: function(table) { + if (table.getElementsByTagName('thead').length == 0) { + // table doesn't have a tHead. Since it should have, create one and + // put the first table row in it. + the = document.createElement('thead'); + the.appendChild(table.rows[0]); + table.insertBefore(the,table.firstChild); + } + // Safari doesn't support table.tHead, sigh + if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0]; + + if (table.tHead.rows.length != 1) return; // can't cope with two header rows + + // Sorttable v1 put rows with a class of "sortbottom" at the bottom (as + // "total" rows, for example). This is B&R, since what you're supposed + // to do is put them in a tfoot. So, if there are sortbottom rows, + // for backward compatibility, move them to tfoot (creating it if needed). + sortbottomrows = []; + for (var i=0; i5' : ' ▴'; + this.appendChild(sortrevind); + return; + } + if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) { + // if we're already sorted by this column in reverse, just + // re-reverse the table, which is quicker + sorttable.reverse(this.sorttable_tbody); + this.className = this.className.replace('sorttable_sorted_reverse', + 'sorttable_sorted'); + this.removeChild(document.getElementById('sorttable_sortrevind')); + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + return; + } + + // remove sorttable_sorted classes + theadrow = this.parentNode; + forEach(theadrow.childNodes, function(cell) { + if (cell.nodeType == 1) { // an element + cell.className = cell.className.replace('sorttable_sorted_reverse',''); + cell.className = cell.className.replace('sorttable_sorted',''); + } + }); + sortfwdind = document.getElementById('sorttable_sortfwdind'); + if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); } + sortrevind = document.getElementById('sorttable_sortrevind'); + if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); } + + this.className += ' sorttable_sorted'; + sortfwdind = document.createElement('span'); + sortfwdind.id = "sorttable_sortfwdind"; + sortfwdind.innerHTML = stIsIE ? ' 6' : ' ▾'; + this.appendChild(sortfwdind); + + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = this.sorttable_columnindex; + rows = this.sorttable_tbody.rows; + for (var j=0; j 12) { + // definitely dd/mm + return sorttable.sort_ddmm; + } else if (second > 12) { + return sorttable.sort_mmdd; + } else { + // looks like a date, but we can't tell which, so assume + // that it's dd/mm (English imperialism!) and keep looking + sortfn = sorttable.sort_ddmm; + } + } + } + } + return sortfn; + }, + + getInnerText: function(node) { + // gets the text we want to use for sorting for a cell. + // strips leading and trailing whitespace. + // this is *not* a generic getInnerText function; it's special to sorttable. + // for example, you can override the cell text with a customkey attribute. + // it also gets .value for fields. + + hasInputs = (typeof node.getElementsByTagName == 'function') && + node.getElementsByTagName('input').length; + + if (node.getAttribute("sorttable_customkey") != null) { + return node.getAttribute("sorttable_customkey"); + } + else if (typeof node.textContent != 'undefined' && !hasInputs) { + return node.textContent.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.innerText != 'undefined' && !hasInputs) { + return node.innerText.replace(/^\s+|\s+$/g, ''); + } + else if (typeof node.text != 'undefined' && !hasInputs) { + return node.text.replace(/^\s+|\s+$/g, ''); + } + else { + switch (node.nodeType) { + case 3: + if (node.nodeName.toLowerCase() == 'input') { + return node.value.replace(/^\s+|\s+$/g, ''); + } + case 4: + return node.nodeValue.replace(/^\s+|\s+$/g, ''); + break; + case 1: + case 11: + var innerText = ''; + for (var i = 0; i < node.childNodes.length; i++) { + innerText += sorttable.getInnerText(node.childNodes[i]); + } + return innerText.replace(/^\s+|\s+$/g, ''); + break; + default: + return ''; + } + } + }, + + reverse: function(tbody) { + // reverse the rows in a tbody + newrows = []; + for (var i=0; i=0; i--) { + tbody.appendChild(newrows[i]); + } + delete newrows; + }, + + /* sort functions + each sort function takes two parameters, a and b + you are comparing a[0] and b[0] */ + sort_numeric: function(a,b) { + aa = parseFloat(a[0].replace(/[^0-9.-]/g,'')); + if (isNaN(aa)) aa = 0; + bb = parseFloat(b[0].replace(/[^0-9.-]/g,'')); + if (isNaN(bb)) bb = 0; + return aa-bb; + }, + sort_alpha: function(a,b) { + if (a[0]==b[0]) return 0; + if (a[0] 0 ) { + var q = list[i]; list[i] = list[i+1]; list[i+1] = q; + swap = true; + } + } // for + t--; + + if (!swap) break; + + for(var i = t; i > b; --i) { + if ( comp_func(list[i], list[i-1]) < 0 ) { + var q = list[i]; list[i] = list[i-1]; list[i-1] = q; + swap = true; + } + } // for + b++; + + } // while(swap) + } +} + +/* ****************************************************************** + Supporting functions: bundled here to avoid depending on a library + ****************************************************************** */ + +// Dean Edwards/Matthias Miller/John Resig + +/* for Mozilla/Opera9 */ +if (document.addEventListener) { + document.addEventListener("DOMContentLoaded", sorttable.init, false); +} + +/* for Internet Explorer */ +/*@cc_on @*/ +/*@if (@_win32) + document.write("